天天看點

從源碼看Spring bean 生命周期

在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方法具體如下:
    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);
    }
               

    由于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 這一個切入點。