Spring bean的生命周期和扩展

AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段

bean生命周期流程

|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 生命周期 | 扩展处理 | 说明 |
| 实例化:createBeanInstance | 构造方法, 如@Autowired的构造方法注入依赖bean | 如UserService构造方法注入AppDAO: > > @Autowired > public UserService(AppDAO appDAO) { > System.out.println("@Autowired appDAO:" + appDAO); > this.appDAO = appDAO; > } > |
| 属性设置:populateBean | 如setter方法注入的依赖 如@Autoware的filed注入 | 如UserService中注入UserDAO: > > @Resource(name = "u") > public void setUserDAO(UserDAO userDAO) { > System.out.println("setUserDAO:" + userDAO); > this.userDAO = userDAO; > } > |
| 初始化:initializeBean | 1. BeanPostProcessor#postProcessBeforeInitialization 2. @PostConstruct 3. InitializingBean#afterPropertiesSet initMethod 4. BeanPostProcessor#postProcessAfterInitialization | 上一步骤属性设置完后,初始化方法前后都可以扩展。 例如BeanPostProcessor#postProcessBeforeInitialization,直接改变了set注入的appDAO对象 > > @Component > public class ServiceBeanPostProcessor implements BeanPostProcessor { > @Override > public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { > // Bean 初始化前的逻辑 > if (beanName.equals("userService")) { > UserService userService = (UserService)bean; > AppDAO appDAO = new AppDAOImpl2(); > userService.setAppDAO(appDAO); > System.out.println("postProcessBeforeInitialization:" + ":" + bean); > } > return bean; > } > |
| 销毁 | 1. @PreDestroy 2. DisposableBean#destroy destroyMethod | |

附org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

java 复制代码
/**
	 * Actually create the specified bean. Pre-creation processing has already happened
	 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
	 * <p>Differentiates between default bean instantiation, use of a
	 * factory method, and autowiring a constructor.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param args explicit arguments to use for constructor or factory method invocation
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 * @see #instantiateBean
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 */
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

扩展执行

接上文:AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,来看这些BeanPostProcessor如何起作用

测试bean定义类如下

java 复制代码
@Service("userService")
public class UserService implements InitializingBean, DisposableBean {

    private String userServiceName;

    private UserDAO userDAO;
    private AppDAO appDAO;

    /**
     * field 注入
     */
    @Autowired
    private CommonService commonService;

    public UserService() {
        System.out.println("constructor");
    }

    /**
     * 类似于 InitializingBean 的 afterPropertiesSet() 方法
     */
    @PostConstruct
    public void init() {
        System.out.println("PostConstruct userService");
        System.out.println("userDAO is not null:" + (userDAO != null));
        System.out.println("appDAO is not null:" + (appDAO != null));
        userServiceName = "selfUserService";
    }

    /**
     * setter注入
     * @param userDAO
     */
    @Resource(name = "u")
    public void setUserDAO(UserDAO userDAO) {
        System.out.println("setUserDAO:" + userDAO);
        this.userDAO = userDAO;
    }

    /**
     * 构造器注入
     * @param appDAO
     */
    @Autowired
    public UserService(AppDAO appDAO) {
        System.out.println("@Autowired appDAO:" + appDAO);
        this.appDAO = appDAO;
    }

    public void add(User user) {
        userDAO.save(user);
    }

    public UserDAO getUserDAO() {
        return userDAO;
    }

    /**
     * 类似于 DisposableBean 的 destroy() 方法
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println("preDestroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet userService");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("destroy userService");

    }

    public void setUserServiceName(String userServiceName) {
        this.userServiceName = userServiceName;
    }

    public void setAppDAO(AppDAO appDAO) {
        this.appDAO = appDAO;
    }

    @Override
    public String toString() {
        return "UserService{" +
                "userServiceName='" + userServiceName + '\'' +
                ", userDAO=" + userDAO +
                ", appDAO=" + appDAO +
                ", commonService=" + commonService +
                '}';
    }
}

InstantiationAwareBeanPostProcessors:SmartInstantiationAwareBeanPostProcessor

推断构造函数,最后是AutowiredAnnotationBeanPostProcessor完成构造函数的推断

最后判断有@Autowired的构造函数 完成实例化过程

InstantiationAwareBeanPostProcessor:CommonAnnotationBeanPostProcessor

populate阶段CommonAnnotationBeanPostProcessor完成setter注入

复制代码
/**
 * setter注入
 * @param userDAO
 */
@Resource(name = "u")
public void setUserDAO(UserDAO userDAO) {
    System.out.println("setUserDAO:" + userDAO);
    this.userDAO = userDAO;
}

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties

java 复制代码
@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
		}
		return pvs;
	}

InstantiationAwareBeanPostProcessor:AutowiredAnnotationBeanPostProcessor

populate阶段AutowiredAnnotationBeanPostProcessor完成@Autorwired的filed的注入,具体可以再次阅读:Spring5.1.3 @Autorwired注解原理重新回顾-CSDN博客

BeanPostProcessor#postProcessBeforeInitialization

复制代码
initializeBean阶段会执行BeanPostProcessor的postProcessBeforeInitialization方法
执行自定义的BeanPostProcessor
执行CommonAnnotationBeanPostProcessor解析@PostConstruct注解
复制代码
@PostConstruct
public void init() {
    System.out.println("PostConstruct userService");
    System.out.println("userDAO is not null:" + (userDAO != null));
    System.out.println("appDAO is not null:" + (appDAO != null));
    userServiceName = "selfUserService";
}

执行InitializingBean的afterPropertiesSet方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

java 复制代码
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}
BeanPostProcessor#postProcessAfterInitialization

InitializingBean最后阶段会执行BeanPostProcessor的postProcessAfterInitialization方法

本例

复制代码
@Component
public class ServiceBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化前的逻辑
        if (beanName.equals("userService")) {
            UserService userService = (UserService)bean;
            AppDAO appDAO = new AppDAOImpl2();
            userService.setAppDAO(appDAO);
            System.out.println("postProcessBeforeInitialization:" + ":" + bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化后的逻辑
        if (beanName.equals("userService")) {
            System.out.println("postProcessAfterInitialization:" + ":" + bean);
        }
        return bean;
    }
}
相关推荐
我想学LINUX1 分钟前
【2024年华为OD机试】 (A卷,100分)- 对称美学(Java & JS & Python&C/C++)
java·c语言·javascript·c++·python·华为od
东北赵四4 分钟前
JVM之垃圾回收器概述(续)的详细解析
java·开发语言·jvm
潜洋7 分钟前
Sping Boot教程之五十四:Spring Boot Kafka 生产者示例
java·spring boot·后端·kafka
李长渊哦16 分钟前
Spring Boot 动态表操作服务实现
java·spring boot·后端
花追雨43 分钟前
Java - Http 通讯
java·开发语言·http
大强的博客1 小时前
《Spring Framework实战》9:4.1.4.依赖注入
java·后端·spring
爱上语文1 小时前
Java后端开发单元测试
java·开发语言·单元测试
码农小灰1 小时前
Java中的反射机制及其应用场景
java·spring
处女座_三月1 小时前
多并发发短信处理(头条项目-07)
java·前端·数据库·python
HHppGo1 小时前
java_抽象类最佳实践-模板设计模式
java·开发语言·设计模式