spring bean 的生命周期一览

我们就从最先执行的setBeanName开始一览,spring bean 的生命周期

setBeanName 的执行流程

先看一波 debug 栈的截图

setBeanName-debug

先是registerBeanPostProcessors这个都熟悉,接下来是 getBean相关的,不关心,我们关心初始化的时候干了嘛,那就从 createBean 开始看起,一定要记着这个时候类的构造方法已经调用过了哦。

createBean方法开始有很多 check ,接着下面这句,猜测是跟代理初始化相关的,我们没添加代理,先放过

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

然后,进入doCreateBean方法,这个方法我们还是直奔 debug 指示的initializeBean方法,其中1783 行的invokeAwareMethods方法里面执行了我们关心的setBeanName方法。仔细的浏览一下这个方法:

private void invokeAwareMethods(final String beanName, final 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);
			}
		}
	}

同时发现不仅setBeanName在这里执行,还有setBeanClassLoadersetBeanFactory也是在这里执行的

再回到doCreateBean方法,往下翻会发现下面这行

// Register bean as disposable.
registerDisposableBeanIfNecessary(beanName, bean, mbd);

点进去看看这里面其实会注册 DisposableBean interface, 自定义的 destroy method。

而这些都是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory这个类里面

setApplicationContext执行流程

再看看setApplicationContext的执行流程和 setBeanName有何不同
setApplicationContext-debug
同样的也是从registerBeanPostProcessors开始,一直到initializeBean,和上面的 setBeanName 都是一样的,只不过这次是到了 1788 行的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization方法,看看这个方法实现

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;
	}

getBeanPostProcessors()取出所有的BeanPostProcessor然后对当前的 bean 执行所有的 processor。即初始化每个 bean 的时候都会经历所有的BeanPostProcessor

再看看上面的截图,自定义的setApplicationContext是在

org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization中执行的,

但是ApplicationContextAwareProcessor是什么时候注入的, 点击引用,发现是在,org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 中手动注入的,按下不表。

回到ApplicationContextAwareProcessor.invokeAwareInterfaces方法,看看有哪些 Aware 接口可以执行:

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 接口都是可以自定义的。

在回头看看org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean()方法,你会发现初始化的扩展点几乎都在这里执行的,相关代码都加上了注释。这下找到源头不怕记不住了。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
      // 1. setBeanName、setBeanClassLoader、setBeanFactory 方法执行
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
      // 2. BeanPostProcessor.postProcessBeforeInitialization 方法执行
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
      // 3. afterPropertiesSet 和 定制的 init-method 执行
			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()) {
      // 4. BeanPostProcessor.postProcessAfterInitialization 方法执行
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

,似乎还漏了点东西。注解!!

@PostConstruct 注解

postConstruct-debug

是不是和上面的流程是一样的,这次只不过是用InitDestroyAnnotationBeanPostProcessor来负责注解的初始化方法执行,只不过这个 processor 的注入是在AnnotatedBeanDefinitionReader初始化的时候。至于先后顺序的话,一向都是注解优先的,这次也不会例外。

可以推断一下实现上是如何让注解优先执行的?

我们在文档中读到了一个接口Ordered,用来指定优先级的,注解的InitDestroyAnnotationBeanPostProcessor就实现了这个接口的增强接口PriorityOrdered,由此确保了@PostConstruct的执行顺序。

初始化相关的几乎都在这里了,总结一下,IOC 容器相关的会先执行,例如 setBeanName,setBeanFactory 等等,接下来的初始化方法都是由内置的BeanPostProcessor-before的实现类的初始化方法,例如 setApplicationContext、postProcessBeforeInitialization、以及注解@PostConstruct;接着是 initMethod 相关方法执行;然后postProcessAfterInitialization 的处理;初始化结束。
这里需要注意的一个点是:如果一个类同时实现了BeanPostProcessor 、InitializingBean,在 getBean 的时候你会发现,哎,先执行了InitializingBean.afterPropertiesSet() 然后才是
BeanPostProcessor.postProcessBeforeInitialization() ,那是什么原因呢,因为BeanPostProcessor是相对于其他 bean 而言的,而InitializingBean确是对当前实例对象的。如果 类A 实现了BeanPostProcessor,类B实现了InitializingBean,那么类 A 的BeanPostProcessor肯定是在类 B 的初始化过程执行 InitializingBean方法之前执行的。

至于销毁,我们在上面看到了是在AbstractAutowireCapableBeanFactory#doCreateBean里面注册的销毁方法,同理@PreDestroy优先。调用时机当然是在容器销毁的时候。至于为什么@PreDestroy可以先执行,也是上面的原因,InitDestroyAnnotationBeanPostProcessor实现了DestructionAwareBeanPostProcessor接口,bean销毁时,也会执行一遍所有的销毁 processor,当然就执行到了@PreDestroy注解的方法。
到这里bean生命周期的大部分就结束了。
附上测试代码

@Component
public class ThingOne implements BeanFactoryAware, ApplicationContextAware,BeanPostProcessor, InitializingBean {


	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("invoke setBeanFactory()");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println("invoke setApplicationContext()");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(this.getClass().getName() + " invoke postProcessBeforeInitialization() to bean:"+bean.getClass().getName()+", beanName:"+beanName);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(this.getClass().getName() + " invoke postProcessAfterInitialization() to bean:"+bean.getClass().getName()+", beanName:"+beanName);
		return bean;
	}

	//1 PostConstruct
	@PostConstruct
	public void postConstructMethod(){
		System.out.println(this.getClass().getName() + " 执行 PostConstruct " +"postConstructMethod");
	}

	@PreDestroy
	public void preDestroyMethod(){
		System.out.println(this.getClass().getName() + " 执行 @PreDestroy " +"preDestroyMethod");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println(this.getClass().getName() + " 执行 InitializingBean 接口 "+ "afterPropertiesSet");
	}
}
/*-------------------------------------------------------------------------*/
@Component
public class ThingTwo implements InitializingBean{

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println(this.getClass().getName() + " 执行 InitializingBean 接口 "+ "afterPropertiesSet");
	}
}
/*-------------------------------------------------------------------------*/
@Configuration
@ComponentScan(basePackages = "org.lifecycle.demo")
public class LifecycleCallbackDemo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifecycleCallbackDemo.class);
		System.out.println(applicationContext.getBean("someThing"));
		applicationContext.close();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章