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();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章