Spring容器啓動流程

        ContextLoaderListener:啓動時,應用戶服務器調用Listener.contextInitialized(ServletContextEvent event)進行初始化整個容器。其初始化大體流程如圖:web

    啓動源碼:
spring

/**
 * 初始化context入口
 * Initialize the root web application context.
 */
@Override
public void contextInitialized(ServletContextEvent event) {
   initWebApplicationContext(event.getServletContext());
}

        ContextLoader:真正實現ApplicationContext。服務器

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
  if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
     
//......
 
}

  ......  

 
long startTime = System.currentTimeMillis();

  try
{
     
// Store context in local instance variable, to guarantee that
     // it is available on ServletContext shutdown.
     
if (this.context == null) {
       
this.context = createWebApplicationContext(servletContext);
     
}
     
if (this.context instanceof ConfigurableWebApplicationContext) {
        ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)
this.context;
        //判斷context是否已經初始化
        if
(!cwac.isActive()) {
           
// The context has not yet been refreshed -> provide services such as
           // setting the parent context, setting the application context id, etc
           //經過web.xml配置的參數locatorFactorySelector等初始化初始化父容器環境,
           
if (cwac.getParent() == null) {
             
// The context instance was injected without an explicit parent ->
              // determine parent for root web application context, if any.
             
ApplicationContext parent = loadParentContext(servletContext);
             
cwac.setParent(parent);
           
}
           
//Context容器[加載resource資源文件、建立bean等]
           configureAndRefreshWebApplicationContext(cwac, servletContext);

       
}
     }
     servletContext.setAttribute(WebApplicationContext.
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

     
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
     if
(ccl == ContextLoader.class.getClassLoader()) {
       
currentContext = this.context;
     
}
     
else if (ccl != null) {
       
currentContextPerThread.put(ccl, this.context);
     
}

     
if (logger.isDebugEnabled()) {
        logger.debug(
"Published root WebApplicationContext as ServletContext attribute with name [" +
              WebApplicationContext.
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
     
}
     
if (logger.isInfoEnabled()) {
       
long elapsedTime = System.currentTimeMillis() - startTime;
       
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
     
}

     
return this.context;
 
}
 
catch (RuntimeException ex) {
     logger.error(
"Context initialization failed", ex);
     
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
     throw
ex;
 
}
 
catch (Error err) {
     logger.error(
"Context initialization failed", err);
     
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
     throw
err;
 
}
}
/**
 * 一、配置web.xml中的參數
 * 二、初始化
 * 實例化beanFactory、讀取resource資源、建立BeanDefinition、加載相關組件
 */
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
   if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
      if (idParam != null) {
         wac.setId(idParam);
      }
      else {
         // Generate default id...
         wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
               ObjectUtils.getDisplayString(sc.getContextPath()));
      }
   }

   wac.setServletContext(sc);
   String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
   if (configLocationParam != null) {
      wac.setConfigLocation(configLocationParam);
   }

   // The wac environment's #initPropertySources will be called in any case when the context
   // is refreshed; do it eagerly here to ensure servlet property sources are in place for
   // use in any post-processing or initialization that occurs below prior to #refresh
   ConfigurableEnvironment env = wac.getEnvironment();
   if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
   }

   //初始化web.xml中配置的自定義contextInitializerClasses等
   customizeContext(sc, wac);
   //加載spring中的配置文件xml、properties等,並建立beanFactory、實例化bean等
   wac.refresh();
}


        AbstractApplicationContext:容器refresh()建立beanFactory、讀取resource資源文件、建立bean;app

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      //一、建立beanFactory(讀取resource、加載BeanDefinition並將其註冊到beanFactory中)
      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      
      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         //beanFactory中添加
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         //註冊BeanPostProcessor,在實例化bean先後調用,可用於修改bean中信息等
         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();
    
         //二、bean實例化
         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);
      
         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }
   }
}

  BeanPostProcessor:自定義BeanPostProcessor的實現能夠用戶處理bean生成先後相關的邏輯,如修改bean信息,監控bean生成等,可分別調用postProcessBeforeInitialization()、postProcessAfterInitialization()兩個方法處理前置和後置邏輯。ide


 一、經過obtainFreshBeanFactory()建立ConfigurableListableBeanFactory,並經過XmlBeanDefinitionReader讀取Resource資源文件,解析爲BeanDefinition。post

/**
 * 建立beanFactory並加載resource資源文件
 * 解析資源文件、裝載BeanDefinition
 * Tell the subclass to refresh the internal bean factory.
 * @return the fresh BeanFactory instance
 * @see #refreshBeanFactory()
 * @see #getBeanFactory()
 */
protected ConfigurableListableBeanFactory() {
   //建立beanFactory並加載resource資源文件
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

AbstractRefreshableApplicationContext:this

@Override
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      //建立beanFactory---DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      //讀取resource、加載BeanDefinition
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

        AbstractXmlApplicationContext:loadBeanDefinitions()經過XmlBeanDefinitionReader讀取Resource資源文件,解析爲BeanDefinition。spa

/**
 * Loads the bean definitions via an XmlBeanDefinitionReader.
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see #initBeanDefinitionReader
 * @see #loadBeanDefinitions
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, , IOException {
    //建立XmlBeanDefinitionReader 
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   //讀取resource、加載BeanDefinition並將其註冊到beanFactory的map中
   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}


        二、實例化bean對象:經過finishBeanFactoryInitialization方法實現.net

相關文章
相關標籤/搜索