IoC容器的啓動過程

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>applicationContext.xml</param-value>
 </context-param>
 
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

如上面web.xml的配置,IoC容器的啓動由ContextLoaderListener這個監聽器做爲入口。java

 public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    /**
      * Initialize the root web application context.
      */
     @Override
     public void contextInitialized(ServletContextEvent event) {
      initWebApplicationContext(event.getServletContext());
     }
 }

在init函數裏調用父類ContextLoader的initWebApplicationContext方法完成webApplicationContext的建立和初始化。web

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc)  {
  //設置servletContext
  wac.setServletContext(sc);
  //配置文件的路徑:applicationContext.xml
  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);
  }
  customizeContext(sc, wac);
  wac.refresh(); //IoC容器的加載過程都在這個函數裏
}

 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext{
        /**
          * This implementation performs an actual refresh of this context's underlying
          * bean factory, shutting down the previous bean factory (if any) and
          * initializing a fresh bean factory for the next phase of the context's lifecycle.
          */
         @Override
         protected final void refreshBeanFactory() throws BeansException {
          if (hasBeanFactory()) {
           destroyBeans();
           closeBeanFactory();
          }
          try {
           DefaultListableBeanFactory beanFactory = createBeanFactory();
           beanFactory.setSerializationId(getId());
           customizeBeanFactory(beanFactory);
           loadBeanDefinitions(beanFactory);  //加載bean的函數
           synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
           }
          }
          catch (IOException ex) {
           throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
          }
         }
}

  bean的加載過程包括:spring

       1. 歷來源處讀取(載入);app

       2. 解析,驗證;ide

       3. 建立;函數

       4. 實例化及依賴對象的注入(若是bean的屬性lazy-init設置true,那麼此時不會有這個步驟,只有等到第一次用到該bean的時候纔去作,及調用getBean時才實例化及依賴注入);post

public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {

     /**
      * 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 {
      // 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(getEnvironment());
      beanDefinitionReader.setResourceLoader(this);
      beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
      // Allow a subclass to provide custom initialization of the reader,
      // then proceed with actually loading the bean definitions.
      initBeanDefinitionReader(beanDefinitionReader);
      loadBeanDefinitions(beanDefinitionReader);
     }
}
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    /**
      * Register the bean definitions contained in the given DOM document.
      * Called by {@code loadBeanDefinitions}.
      * <p>Creates a new instance of the parser class and invokes
      */
     public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
      BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
      documentReader.setEnvironment(this.getEnvironment());
      int countBefore = getRegistry().getBeanDefinitionCount();
      documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
      return getRegistry().getBeanDefinitionCount() - countBefore;
     }
}
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
     @Override
     public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
      this.readerContext = readerContext;
      logger.debug("Loading bean definitions");
      Element root = doc.getDocumentElement();
      doRegisterBeanDefinitions(root);
     }
}

bean的信息是在BeanDefinition中定義的,解析出來的bean的信息是放在HashMap中存儲的。ui

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
  
   /** Map of bean definition objects, keyed by bean name */
   private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
   @Override
 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
   throws BeanDefinitionStoreException {
        this.beanDefinitionMap.put(beanName, beanDefinition);
   }
  }

getBean是獲取bean的地方,也是注入依賴的地方(遞歸調用)this

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @SuppressWarnings("unchecked")
     protected <T> T doGetBean(
       final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
       throws BeansException {
           // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
             for (String dependsOnBean : dependsOn) {
              if (isDependent(beanName, dependsOnBean)) {
               throw new BeanCreationException("Circular depends-on relationship between '" +
                 beanName + "' and '" + dependsOnBean + "'");
              }
              registerDependentBean(dependsOnBean, beanName);
              getBean(dependsOnBean);
             }
            }
       }
}

上面就是IoC容器加載過程當中最重要的幾個地方。spa

相關文章
相關標籤/搜索