码迷,mamicode.com
首页 > 其他好文 > 详细

IoC容器的启动过程

时间:2015-05-13 14:58:37      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:

 <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这个监听器作为入口。

 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的创建和初始化。

技术分享

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的加载过程包括:

       1. 从来源处读取(载入);

       2. 解析,验证;

       3. 创建;

       4. 实例化及依赖对象的注入(如果bean的属性lazy-init设置true,那么此时不会有这个步骤,只有等到第一次用到该bean的时候才去做,及调用getBean时才实例化及依赖注入);

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中存储的。

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的地方,也是注入依赖的地方(递归调用)

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容器加载过程中最重要的几个地方。

 

 

IoC容器的启动过程

标签:

原文地址:http://my.oschina.net/u/1177710/blog/414323

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!