1. 程式人生 > >從原始碼看Spring bean 生命週期

從原始碼看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 這一個切入點。