zoukankan      html  css  js  c++  java
  • spring源码学习之:spring容器的applicationContext启动过程

     Spring 容器像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式进行工作。如果我们将Spring容器比喻为一辆汽车,可以将 BeanFactory看成汽车的发动机,而ApplicationContext则是 整辆汽车,它不但包括发动机,还包括离合器、变速器以及底盘、车身、电气设备等其他组件。在ApplicationContext内,各个组件按部就班、 有条不紊地完成汽车的各项功能。

    ApplicationContext内部封装 了一个BeanFactory对象,来实现对容器的操作,初始化完成之后,BeanFactory封装了bean的信息,而 ApplicationContext通过访问这个对象获取bean的对象信息(BeanDefinition/Bean对象,都是由 BeanFactory实际创建并管理的),为了实现接口的统一,ApplicationContext也实现了一系列的BeanFactory接口(可 以说ApplicationContext对BeanFactory对象实现一种代理)。ApplicationContext建立在 BeanFactory的基础之上,对配置对象的管理最终还是交于一个DefaultListableBeanFactory来完成(装配地址/访问 等),而ApplicationContext在应用这个DefaultListableBeanFactory对象的基础上,不 仅实现了BeanFactory接口提供的功能方法,并且黏合了一些面向应用的功能,如资源/国际化支持/框架事件支持等,并且将一些原先需要手动设置到 BeanFactory的属性通过配置文件中配置的形式代替(如工厂后处理器 BeanPostProcessor/InstantiationAwareBeanPostProcessor)

    同样,因为对于BeanDefinition和 bean对象的管理是由上下文持有的beanfactory对象完成的,用户不需要拥有这样的接口,因此,ApplicationContext的接口体 系中并没有BeanDefinitionRegistry,SingletonBeanRegistry以及 AutowireCapableBeanFactory接口(ApplicationContext可以访问一些接口方法在上述接口中也定义,但这些方法 提供者为BeanFactory体系中的其他接口,BeanFactory接口体系中的接口之间有重复定义方法的)。

     

    内部工作机制(Spring容器ApplicationContext的初始化                                                                                    

    (一) 首先来看创建ApplicationContext ,以ClassPathXmlApplicationContext为例:

    ApplicationContext = new ClassPathXmlApplicationContext(xmlPath);  

    源码如下:

    public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
                      this(new String[] {configLocation});
           }

    public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
                      this(configLocations, (ApplicationContext) null);
           }

    //。。。。。。省略几个重载的构造函数

    public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent)
                                                                                                                             throws BeansException {

              super(parent);
                     this.configLocations = configLocations;

              //IoC容器的初始化过程,其初始化过程的大致步骤由AbstractApplicationContext来定义   
                     refresh();
           }

    关键之处在于refresh方法,此方法继承于ClassPathXmlApplicationContext的间接父类:

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
                                                            implements ConfigurableApplicationContext, DisposableBean
    {

    Spring的AbstractApplicationContext是 ApplicationContext抽象实现类,该抽象类的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过 程清晰刻画了Spring容器启动时所执行的各项操作(创建Spring容器如ClassPathXmlApplicationContext)。下面, 我们来看一下refresh()内部定义了哪些执行逻辑:

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

                 // Tell the subclass to refresh the internal bean factory       

                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();--------(1)

                 // Prepare the bean factory for use in this context.
                        prepareBeanFactory(beanFactory);

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

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

                       // Register bean processors that intercept bean creation
                              registerBeanPostProcessors(beanFactory);---------------------------------------------(3)

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

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

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

                       // Check for listener beans and register them.
                              registerListeners();----------------------------------------------------------------------------(7)

                       // Instantiate singletons this late to allow them to access the message source.
                              beanFactory.preInstantiateSingletons();--------------------------------------------------(8)

                       // Last step: publish corresponding event.
                              publishEvent(new ContextRefreshedEvent(this));---------------------------------------(9)
                        } catch (BeansException ex) {
                              // Destroy already created singletons to avoid dangling resources.
                              beanFactory.destroySingletons();
                              throw ex;
                       }
                 }
           }

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
                 refreshBeanFactory();
                 ConfigurableListableBeanFactory beanFactory = getBeanFactory();

          return beanFactory;
           } 

    protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

    public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

     

    1.初始化BeanFactory:根据配置文件实例化 BeanFactory,getBeanFactory()方法由具体子类实现。在这一步里,Spring将配置文件的信息解析成为一个个的 BeanDefinition对象并装入到容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还未初始 化;obtainFreshBeanFactory()会调用自身的refreshBeanFactory(),而 refreshBeanFactory()方法由子类AbstractRefreshableApplicationContext实现,该方法返回了一个创建的DefaultListableBeanFactory对象,这个对象就是由ApplicationContext管理的BeanFactory容器对象

    这一步的操作相当于,如果我们在自己的应用代码中不用ApplicationContext而直接用BeanFactory时创建BeanFactory对象的操作

    核心代码如下:

    public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { }

     /** 该ApplicationContext管理的BeanFactory容器对象*/
           private DefaultListableBeanFactory beanFactory;

    protected final void refreshBeanFactory() throws BeansException {
                  // Shut down previous bean factory, if any.
                  ConfigurableListableBeanFactory oldBeanFactory = null;
                  synchronized (this.beanFactoryMonitor) {
                          oldBeanFactory = this.beanFactory;
                  }
                  if (oldBeanFactory != null) {
                          oldBeanFactory.destroySingletons();
                          synchronized (this.beanFactoryMonitor) {
                                 this.beanFactory = null;
                          }
                  }

           // Initialize fresh bean factory.
                  try {

                   // 创建容器对象
                          DefaultListableBeanFactory beanFactory = createBeanFactory();

                   // Customize the internal bean factory used by this context
                          customizeBeanFactory(beanFactory);

                   // 装载配置文件,并传入相关联的BeanFactory对象,作为BeanDefinition的容器
                          loadBeanDefinitions(beanFactory);
                          synchronized (this.beanFactoryMonitor) {
                                this.beanFactory = beanFactory;
                          }
                  }  catch (IOException ex) {
                          throw new ApplicationContextException(
                                      "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
                  }
           }

    // 创建Spring默认的容器对象

    protected DefaultListableBeanFactory createBeanFactory() {
                  return new DefaultListableBeanFactory(getInternalParentBeanFactory());
           }

    // 该方法为一个钩子方法,子类可以覆盖它对当前上下文管理的BeanFactory提供客户化操作,也可以忽略

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
           }

    // 装载配置文件的方法,需要子类实现

    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
                                                                                                         throws IOException, BeansException;

     

    对于上面装载配置文件的方法,由其子类扩展实现:

    public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext  {}

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
                 // 使用XMLBeanDefinitionReader来载入bean定义信息的XML文件,传入关联的BeanFactory

          XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

          // 这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的
                 // 因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递入

          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);

          // 这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理 
                 loadBeanDefinitions(beanDefinitionReader);
           } 

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
                 Resource[] configResources = getConfigResources();
                 if (configResources != null) {
                         reader.loadBeanDefinitions(configResources);
                 }
                 String[] configLocations = getConfigLocations();
                 if (configLocations != null) {
                         reader.loadBeanDefinitions(configLocations);
                 }
           }

    reader.loadBeanDefinitions(configLocations);涉及到XmlBeanDefinitionReader 工具类的使用(以后整理

    2.调用工厂后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanFactoryPostProcessor类型的Bean,并调用其postProcessBeanFactory()接口方法;

    经过第一步加载配置文件,已经把配置文件中定义的所有bean装载到 BeanDefinitionRegistry这个Beanfactory中,对于ApplicationContext应用来说这个 BeanDefinitionRegistry类型的BeanFactory就是Spring默认的 DefaultListableBeanFactory

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
                                                               implements ConfigurableListableBeanFactory, BeanDefinitionRegistry

    在这些被装载的bean中,若有类型为BeanFactoryPostProcessor的bean(配置文件中配置的),则将对应的BeanDefinition生成BeanFactoryPostProcessor对象

    容器扫描BeanDefinitionRegistry中的BeanDefinition,使 用java反射自动识别出Bean工厂后处理器(实现BeanFactoryPostProcessor接口)的bean,然后调用这些bean工厂后处 理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理,可以完成以下两项工作(当然也可以有其他的操作,用 户自己定义):

    1 对使用到占位符的<bean>元素标签进行解析,得到最终的配置值,这意味着对一些半成品式的BeanDefinition对象进行加工处理 并取得成品的BeanDefinition对象。2 对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean(实现 java.beans.PropertyEditor接口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中 (PropertyEditorRegistry),这个Spring提供了实现:CustomEditorConfigurer,它实现了 BeanFactoryPostProcessor,用它来在此注册自定义属性编辑器;

    AbstractApplicationContext中的代码如下:

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
                 // Invoke factory processors registered with the context instance.
                 for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
                       BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
                       factoryProcessor.postProcessBeanFactory(beanFactory);
                 }

          // Do not initialize FactoryBeans here: We need to leave all regular beans
                 // 通过ApplicatinContext管理的beanfactory获取已经注册的BeanFactoryPostProcessor类型的bean的名字

                 String[] factoryProcessorNames =
                                  beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

          // Separate between BeanFactoryPostProcessors that implement the Ordered
                 // interface and those that do not.
                 List orderedFactoryProcessors = new ArrayList();
                 List nonOrderedFactoryProcessorNames = new ArrayList();
                 for (int i = 0; i < factoryProcessorNames.length; i++) {
                       if (isTypeMatch(factoryProcessorNames[i], Ordered.class)) {

                       // 调用beanfactory的getBean取得所有的BeanFactoryPostProcessor对象
                             orderedFactoryProcessors.add(beanFactory.getBean(factoryProcessorNames[i]));
                       }
                       else {
                             nonOrderedFactoryProcessorNames.add(factoryProcessorNames[i]);
                       }
                 }

          // First, invoke the BeanFactoryPostProcessors that implement Ordered.
                 Collections.sort(orderedFactoryProcessors, new OrderComparator());
                 for (Iterator it = orderedFactoryProcessors.iterator(); it.hasNext();) {
                      BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();

               // 执行BeanFactoryPostProcessor的方法,传入当前持有的beanfactory对象,以获取要操作的 

               // BeanDefinition
                      factoryProcessor.postProcessBeanFactory(beanFactory);
                 }
                 // Second, invoke all other BeanFactoryPostProcessors, one by one.
                 for (Iterator it = nonOrderedFactoryProcessorNames.iterator(); it.hasNext();) {
                      String factoryProcessorName = (String) it.next();
                      ((BeanFactoryPostProcessor) getBean(factoryProcessorName)).

                                                                          postProcessBeanFactory(beanFactory);
                 }
           }

     

    BeanFactoryPostProcessor接口代码如下,实际的操作由用户扩展并配置(扩展点,如何扩展?

    package org.springframework.beans.factory.config;

    public interface BeanFactoryPostProcessor {

         /**
                 * Modify the application context's internal bean factory after its standard
                */
                 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

    }

     

    3.注册Bean后处理器:根据反射机制从BeanDefinitionRegistry中找出所有BeanPostProcessor类型的Bean,并将它们注册到容器Bean后处理器的注册表中;

    AbstractApplicatinContext中对应代码如下:

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
                  String[] processorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

             // Register BeanPostProcessorChecker that logs an info message when
                    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 +  

                                                                                                                            processorNames.length;
                    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory,  

                                                                                                                    beanProcessorTargetCount));
                    List orderedProcessors = new ArrayList();
                    List nonOrderedProcessorNames = new ArrayList();  

             for (int i = 0; i < processorNames.length; i++) {
                          if (isTypeMatch(processorNames[i], Ordered.class)) {
                               orderedProcessors.add(getBean(processorNames[i]));
                          }
                          else {
                               nonOrderedProcessorNames.add(processorNames[i]);
                          } 
                    }

             // First, register the BeanPostProcessors that implement Ordered.
                    Collections.sort(orderedProcessors, new OrderComparator());
                    for (Iterator it = orderedProcessors.iterator(); it.hasNext();) {

                   // 注册bean后处理器,该方法定义于ConfigurableBeanFactory接口
                          beanFactory.addBeanPostProcessor((BeanPostProcessor) it.next());
                    }
                    // Second, register all other BeanPostProcessors, one by one.
                    for (Iterator it = nonOrderedProcessorNames.iterator(); it.hasNext();) {
                          String processorName = (String) it.next();
                          beanFactory.addBeanPostProcessor((BeanPostProcessor) getBean(processorName));
                    }
           }

    整段代码类似于第三步的调用工厂后处理器,区别之处在于,工厂后处理器在获取后立即调用,而 Bean后处理器在获取后注册到上下文持有的beanfactory中,供以后操作调用(在用户获取bean的过程中,对已经完成属性设置工作的Bean 进行后续加工,他加工的是bean,而工厂后处理器加工的是BeanDefinition)

    BeanPostProcessor 接口代码如下,实际的操作由用户扩展并配置(扩展点,如何扩展?

    package org.springframework.beans.factory.config;

    public interface BeanPostProcessor {
                 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
                 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

    }

     

    4.初始化消息源:初始化容器的国际化信息资源;

    源代码如下:

    protected void initMessageSource() {
                    // 补充
           }

     

    5.初始化应用上下文事件广播器;(观察者模式中的具体主题角色,持有观察者角色的集合,称为注册表)

    AbstractApplciationContext拥有一个 applicationEventMulticaster 成员变量,applicationEventMulticaster 提供了容器监听器的注册表,成其为事件广播器。在第七步中将会将事件监听器装入其中

    AbstractApplicationContext中的代码如下:

    private ApplicationEventMulticaster applicationEventMulticaster;

    protected void initApplicationEventMulticaster() {

            // "applicationEventMulticaster",先看配置文件中有无配置该类型类(用户扩展 扩展点,如何扩展
                   if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
                        this.applicationEventMulticaster = (ApplicationEventMulticaster)
                        getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
                   }
                   else {

                  // 若没有,则应用Spring框架提供的事件广播器实例
                         this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();
                   }
           }
           public boolean containsLocalBean(String name) {
                   return getBeanFactory().containsLocalBean(name);
           }

    public Object getBean(String name, Class requiredType) throws BeansException {
                  return getBeanFactory().getBean(name, requiredType);
           }

    Spring初始化事件广播器,用户可以在配置文件中为容器定义一个自定义的事件广播器 (bean的名称要为"applicationEventMulticaster"),只要实现ApplicationEventMulticaster 就可以了,Spring在此会根据beanfactory自动获取。如果没有找到外部配置的事件广播器,Spring使用 SimpleApplicationEventMulticaster作为事件广播器。

     

    6.初始化其他特殊的Bean:这是一个钩子方法,子类可以借助这个钩子方法执行一些特殊的操作:如AbstractRefreshableWebApplicationContext就使用该钩子方法执行初始化ThemeSource的操作;

    protected void onRefresh() throws BeansException {(扩展点,如何扩展

    package org.springframework.context;
                // For subclasses: do nothing by default.
           }

     

    7.注册事件监听器;(观察者模式中的观察者角色)

    Spring根据上下文持有的beanfactory对象,从它的 BeanDefinitionRegistry中找出所有实现 org.springfamework.context.ApplicationListener的bean,将BeanDefinition对象生成 bean,注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中

    AbstractApplicationContext中的代码如下:

    /** Statically specified listeners */

    private List applicationListeners = new ArrayList();

    public List getApplicationListeners() {
                  return this.applicationListeners;
           }

    protected void registerListeners() {
                  // Register statically specified listeners first.
                  for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
                         addListener((ApplicationListener) it.next());
                  }
                  // 获取ApplicationListener类型的所有bean,即事件监听器
                  // uninitialized to let post-processors apply to them!
                  Collection listenerBeans = getBeansOfType(ApplicationListener.class, true, false).values();
                  for (Iterator it = listenerBeans.iterator(); it.hasNext();) {

                  // 将事件监听器装入第五步初始化的事件广播器
                         addListener((ApplicationListener) it.next());
                  }
           }

    public Map getBeansOfType(Class type, boolean includePrototypes, boolean allowEagerInit)
                                                                                                                              throws BeansException {

             return getBeanFactory().getBeansOfType(type, includePrototypes, allowEagerInit);
           }

    protected void addListener(ApplicationListener listener) {
                    getApplicationEventMulticaster().addApplicationListener(listener);
           }

    ApplicationListener 的源代码如下:(扩展点,如何扩展

    package org.springframework.context;

    import java.util.EventListener;

    /**
            * Interface to be implemented by application event listeners.
            * @see org.springframework.context.event.ApplicationEventMulticaster
           */
           public interface ApplicationListener extends EventListener {
                    void onApplicationEvent(ApplicationEvent event);

    }

     

    8.初始化singleton的Bean:实例化所有singleton的Bean,并将它们 放入Spring容器的缓存中;这就是和直接在应用中使用BeanFactory的区别之处,在创建ApplicationContext对象时,不仅创 建了一个BeanFactory对象,并且还应用它实例化所有单实例的bean。

    AbstractApplicationContext中的代码如下:

    beanFactory.preInstantiateSingletons();

    关于BeanFactory体系的代码参照。。。。。。

     

    9.发布上下文刷新事件:在此处时容器已经启动完成,发布容器refresh事件(ContextRefreshedEvent)

    创建上下文刷新事件,事件广播器负责将些事件广播到每个注册的事件监听器中。

    publishEvent(new ContextRefreshedEvent(this));

    public void publishEvent(ApplicationEvent event) {
                  Assert.notNull(event, "Event must not be null");

           // 在此获取事件广播器,并调用其方法发布事件:调用所有注册的监听器的方法
                  getApplicationEventMulticaster().multicastEvent(event);
                  if (this.parent != null) {
                        this.parent.publishEvent(event);
                  }
           }

     

    至此,ApplicationContext对象就完成了初始化工作:创建 BeanFactory来装配BeanDefiniton,加工处理BeanDefiniton,注册了bean后处理器,初始化了消息资源,初始化了应 用上下文事件广播器,注册了事件监听器,初始化了所有singleton的bean,最后发布上下文刷新事件

  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/5881539.html
Copyright © 2011-2022 走看看