在Spring中,bean一般都以單例模式存在,除非我們将singleton屬性設為false。 單例在多線程的環境下需要考慮線程安全的問題,對于一些公共的資源或資料應該怎麼處理才能保證安全,應該在什麼時機通路這些資源最恰當。 熟悉了spring bean的整個生命周期對于回答這些問題很有幫助。下面我們來看看spring bean從建立到銷毀都經曆了哪些階段:
一、bean 建立過程
在bean初始化方法:AbstractAutowireCapableBeanFactory#initializeBean中:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = 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;
}
1、可以看到先調用invokeAwareMethods,具體如下:
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
可以看到依次調用了setBeanName --> setBeanClassLoader --> setBeanFactory 三個方法,用于在需要的時候設定對應值
2、 然後調用applyBeanPostProcessorsBeforeInitialization,依次執行所有bean post processors 的postProcessBeforeInitialization方法。注意:這裡的processors除了包括我們自定義的processors,還包括spring自身添加的processors. 這裡羅列幾個和spring bean生命周期相關的processor和其添加時機.
- ApplicationContextAwareProcessor:主要用于處理ApplicationContextAware接口的setApplicationContext方法,具體參見ApplicationContextAwareProcessor的postProcessBeforeInitialization方法,在該方法中,調用了ApplicationContextAwareProcessor#invokeAwareInterfaces方法,具體代碼如下:
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
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);
}
}
}
可以看到這裡會依次處理EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware , ApplicationEventPublisherAware , MessageSourceAware , ApplicationContextAware. 那麼ApplicationContextProcessor是什麼時候添加進來的呢,在AbstractApplicationContext#refresh的方法中,在prepareBeanFactory代碼段,可以看到有如下代碼:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 配置上下文相關的回調
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
}
可以看到在初始化bean factory的準備環節中添加了該處理器.
- ServletContextAwareProcessor:主要用于處理Servlet 上下文相關的資訊感覺.其postProcessBeforeInitialization方法具體如下:
這裡一次處理了ServletContextAware和ServletConfigAware接口對應的方法. ServletContextAwareProcessor也是在AbstractApplicationContext#refresh時添加的,在prepareBeanFactory(添加ApplicationContextProcessor)後,調用了postProcessBeanFactory(beanFactory);處理processor的方法,該方法代碼如下:public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (getServletContext() != null && bean instanceof ServletContextAware) { ((ServletContextAware) bean).setServletContext(getServletContext()); } if (getServletConfig() != null && bean instanceof ServletConfigAware) { ((ServletConfigAware) bean).setServletConfig(getServletConfig()); } return bean; }
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }
由于processors是在一個ArrayList中維護,是以會按照順序來執行,也就是說ApplicationContextProcessor和ServletContextAwareProcessor會先于其他spring後面添加或者我們自定義的處理器,是以其對應的Aware的切入點也會先于其他bean post processors先執行,是以bean的生命周期就先aware切入,然後才是其他切入點. 3、接着調用invokeInitMethods方法:也即處理InitializingBean接口中的afterPropertiesSet方法,然後調用使用者自定義的初始化方法,也即通過init-method配置的方法。InitializingBean的afterPropertiesSet需要相應類實作該接口,會使對應類與Spring耦合,而通過init-method則不會.
4、最後調用applyBeanPostProcessorsAfterInitialization處理bean post processor的postProcessAfterInitialization切入點.
到此為止,spring bean就已經準備好可以使用了。
二、bean銷毀
然後在bean factory關閉的時候會處理 DisposableBean對應的destroy方法和自定義的destroy(即destroy-method).
三、bean生命周期
現在我們可以得出一個bean的生命周期應該如下所述:
初始化(執行個體化) --> 屬性設定(自動注入屬性) --> BeanNameAware#setBeanName (--> BeanClassLoaderAware#setBeanClassLoader) -- > BeanFactoryAware#setBeanFactory --> (EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware , ApplicationEventPublisherAware , MessageSourceAware)ApplicationContextAware#setApplicationContext --> BeanPostProcessor#postProcessBeforeInitialization --> InitializingBean#afterPropertiesSet(-->自定義初始化方法) --> BeanPostProcessor#postProcessAfterInitialization --> Bean可以正常使用 --> DisposableBean#destroy (-->自定義銷毀方法)
其中紅色的是比較常用的一些切入點組成的生命周期,另外這裡主要分析ApplicationContext來作為容器時,bean的生命周期。如果是其他的BeanFactory,則沒有上面生命周期流程的:ApplicationContextAware#setApplicationContext 這一個切入點。