從原始碼看Spring bean 生命週期
阿新 • • 發佈:2019-01-30
在Spring中,bean一般都以單例模式存在,除非我們將singleton屬性設為false。 單例在多執行緒的環境下需要考慮執行緒安全的問題,對於一些公共的資源或資料應該怎麼處理才能保證安全,應該在什麼時機訪問這些資源最恰當。 熟悉了spring bean的整個生命週期對於回答這些問題很有幫助。下面我們來看看spring bean從建立到銷燬都經歷了哪些階段:
一、bean 建立過程
在bean初始化方法:AbstractAutowireCapableBeanFactory#initializeBean中:1、可以看到先呼叫invokeAwareMethods,具體如下: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; }
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
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方法具體如下:
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; }
這裡一次處理了ServletContextAware和ServletConfigAware介面對應的方法. ServletContextAwareProcessor也是在AbstractApplicationContext#refresh時新增的,在prepareBeanFactory(新增ApplicationContextProcessor)後,呼叫了postProcessBeanFactory(beanFactory);處理processor的方法,該方法程式碼如下: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); }
二、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 這一個切入點。