我們就從最先執行的setBeanName開始一覽,spring bean 的生命週期
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
在這裏執行,還有setBeanClassLoader
和setBeanFactory
也是在這裏執行的。
再回到doCreateBean
方法,往下翻會發現下面這行
// Register bean as disposable.
registerDisposableBeanIfNecessary(beanName, bean, mbd);
點進去看看這裏面其實會註冊 DisposableBean interface, 自定義的 destroy method。
而這些都是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
這個類裏面
setApplicationContext執行流程
再看看setApplicationContext
的執行流程和 setBeanName
有何不同
同樣的也是從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 註解
是不是和上面的流程是一樣的,這次只不過是用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();
}
}