从源码角度解析Spring Bean 生命周期

Spring Bean生命周期是Spring中重要知识点,对于Bean的拓展十分重要。但想要完全记住整个生命周期并不容易,本文从源码入手解析Spring Bean的生命周期,结合示意图,比较容易记忆。

首先,为方便记忆,将Bean的生命周期主要分为四个阶段,然后在这四个阶段之间穿插各种拓展点。

四类基本生命周期

这四类分别是:

  1. Instantiation 实例化
  2. Populate 属性赋值
  3. Initialization 初始化
  4. Destruction 销毁

源码的入口在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类的doCreateBean方法。

// 忽略无关代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
	......
	
	// Instantiate the bean.
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	
	......
	
	try {
		populateBean(beanName, mbd, instanceWrapper);
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	
	......
		
}

其中第一阶段实例化Bean对应createBeanInstance(beanName, mbd, args)方法, 第二阶段属性赋值对应populateBean(beanName, mbd, instanceWrapper), 第三阶段对应方法initializeBean(beanName, exposedObject, mbd),至于第四阶段Bean的销毁是在容器关闭时调用的,详见ConfigurableApplicationContext#close()

看一下populateBean(beanName, mbd, instanceWrapper)函数源码

// 忽略无关代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
	// state of the bean before properties are set. This can be used, for example,
	// to support styles of field injection.
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
	}

	......
	
	if (pvs != null) {
		// 属性赋值
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

第一类拓展点 InstantiationAwareBeanPostProcessor

可以看到,在第一阶段实例化Bean和第二阶段属性赋值之前,会调用所有InstantiationAwareBeanPostProcessor类的postProcessAfterInstantiation(Object bean, String beanName) 方法, 改变Bean的状态。
在这里插入图片描述
InstantiationAwareBeanPostProcessor继承至接口BeanPostProcessor, 和postProcessAfterInstantiation(Object bean, String beanName)相呼应的还有一个方法是postProcessBeforeInstantiation(Class<?> beanClass, String beanName),从名字上可以看出,应该是在实例化Bean之前执行。

这部分代码在调用doCreateBean方法的createBean方法中


protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
	}
	
	......
	
	try {
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	}
	return beanInstance;
}
protectedObject resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

可以看到,postProcessBeforeInstantiation在doCreateBean之前调用,也就是在bean实例化之前调用的,英文源码注释解释道该方法的返回值会替换原本的Bean作为代理,这也是Aop等功能实现的关键点。

所以这里归纳出第一类拓展点InstantiationAwareBeanPostProcessor, 这些接口会切入到多个Bean的生命周期中,并在实例化Bean前后完成Aop,状态改变等功能。

看下初始化阶段initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		
		.......	
	
		invokeAwareMethods(beanName, bean);
		
		......
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

会先调用invokeAwareMethods方法,然后再调用applyBeanPostProcessorsBeforeInitialization, 再调用invokeInitMethods方法进行初始化,最后调用applyBeanPostProcessorsAfterInitialization方法。
invokeInitMethods方法会判断Bean是否实现了InitializingBean接口,如果是,则调用InitializingBean接口的afterPropertiesSet()方法进行初始化,然后再使用invokeCustomInitMethod(beanName, bean, mbd)方法调用用户自定义的Bean初始化方法。

第二类拓展点 Aware Group One

但在初始化之前会先调用invokeAwareMethods方法和applyBeanPostProcessorsBeforeInitialization

private void invokeAwareMethods(String beanName, Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

从代码可以归纳出第二类拓展点Aware Group One,让Bean感知BeanName,BeanClassLoader, BeanFactory。
为什么这里是Group One,因为后面还有Aware Group Two。

第三类拓展点 BeanPostProcessor

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

该方法调用所有BeanPostProcessorpostProcessBeforeInitialization
在这里插入图片描述
InstantiationAwareBeanPostProcessor一样,和postProcessBeforeInitialization对应的还有一个postProcessAfterInitialization,从方法名也可以看出这个方法应该是在初始化阶段完成后执行。applyBeanPostProcessorsAfterInitialization方法会调用所有BeanPostProcessorpostProcessAfterInitialization方法。

所以这里归纳出第三个扩展点,在实例化前后会分别调用BeanPostProcessorpostProcessBeforeInitialization方法和applyBeanPostProcessorsAfterInitialization方法。

第四类拓展点 Aware Group Two

还有Aware Group Two呢?
在Spring容器中一个BeanPostProcessorApplicationContextAwareProcessor,它的postProcessBeforeInitialization 方法如下

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}
		
		......
		
		invokeAwareInterfaces(bean);	
		return bean;
	}
private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

从上面可以归纳出第四类拓展点Aware Group Two, 它会让Bean感知Environment, EmbeddedValueResolver, ResourceLoader, ApplicationEventPublisher, MessageSource, ApplicationContext。

最后归纳如下图在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值