Spring容器的基本实现之源码分析-下篇

​ 本文接着上一篇 《Spring容器的基本实现之源码分析-上篇》 接着来继续分析 Spring容器启动流程。

​ 本篇将会讨论 Spring 启动流程中剩下的几个核心方法, 包括 BeanFactory 后处理、初始化非延迟加载单例、finishRefresh这几个方法的具体流程。

下篇目录:


下篇目录.png

BeanFactory 的后处理

BeanFactory 作为 Spring 中容器功能的基础,用于存放所有已加载的 bean ,为了保证程序的高度可扩展, Spring 针对 BeanFactory 做了大量的扩展,比如我们熟知的 PostProcessor 等都是在这里实现的。

激活注册的BeanFactoryPostProcessor

​ 首先我们先了解下BeanFactoryPostProcessor的用法。简单来说 BeanFactoryPostProcessor 和前面说的BeanPostProcessor类似,可以对bean的定义(配置元数据) 进行处理。那么它们之前的区别是什么呢?

简单来说,SpringIOC 允许BeanFactoryPostProcessor 在容器实际实例化任何其他的bean之前读取配置的元数据,它的作用于是容器级的,如果是想改变实际的bean实例,那么最好还是使用 BeanPostProcessor 。在 Spring中存在对于 BeanFactoryPostProcessor 的典型应用,比如 PropertyPlaceholderConfigurer。

  1. BeanFactoryPostProcessor 的典型应用: PropertyPlaceholderConfigurer

    我们在配置Spring的Bean描述文件时,经常会使用属性变量引用:

        <bean id="helloMessage" class="com.ccgogoing.domain.HelloMessage">
            <property name="meg" value="${bean.message}"/>
        </bean>
    

    这种使用变量的方式,就是Spring的分散配置,可以在另外的配置文件中为 bean.message 指定值。如在 bean.properties 文件中指定:

    bean.message=Hello World!
    

    当访问bean时,其属性就会被置为配置的字符串,但问题是Spring怎样知道存在这样的配置文件呢? 这就要靠 PropertyPlaceholderConfigurer 这个类的bean:

        <bean id="msgHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>config/bean.properties</value>
                </list>
            </property>
        </bean>
    

在这个bean中指定了配置文件为 config/bean.properties ,这里我们似乎明白了,但仔细想一下,这个"msgHandler" 只是配置为Spring管理的一个 Bean,并没有被别的bean或者对象引用,Spring 的 BeanFactory 怎样知道要从这个 bean中获取配置信息呢?

​ 查看 PropertyPlaceholderConfigurer 的层次结构,可以看到这个类间接继承了 BeanFactoryPostProcessor 接口。这是一个很特别的接口,当Spring加载任何实现了这个接口的bean的配置时,都会在 bean 工厂载入所有bean 的配置之后执行 postProcessorBeanFactory 方法。在 PropertyResourceConfigurer 类中实现了postProcessorBeanFactory 方法,在方法中先后调用了 mergeProperties、 convertProperties、 processProperties这三个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置的内容告知BeanFactory。

PlaceholderConfigurerSupport层级.jpg
@Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            Properties mergedProps = mergeProperties();

            // Convert the merged properties, if necessary.
            convertProperties(mergedProps);

            // Let the subclass process the properties.
            processProperties(beanFactory, mergedProps);
        }
        catch (IOException ex) {
            throw new BeanInitializationException("Could not load properties", ex);
        }
    }

​ 正是通过实现 BeanFactoryPostProcessor 接口, BeanFactory 会在实例化任何 bean 之前获得配置信息,从而能够正确解析 bean 描述文件中的变量引用。

  1. 使用自定义的 BeanFactoryPostProcessor

    我们实现一个 BeanFactoryPostProcessor ,去除潜在的‘流氓’属性值来展示自定义 BeanFactoryPostProcessor 的创建和使用,例如在 bean 定义中留下 bollocks 这样的字眼。

    配置文件 beans.xml

    <bean id="bfpp" class="com.ccgogoing.domain.ObScenityRemovingBeanFactoryPostProcessor">
        <property name="obscenties">
            <set>
                <value>bollocks</value>
                <value>winky</value>
                <value>bum</value>
                <value>MicroSoft</value>
            </set>
        </property>
    </bean>

    <bean id="simple" class="com.ccgogoing.domain.SimplePostProcessor">
        <property name="password" value="bollocks"/>
        <property name="username" value="imaginecup"/>
        <property name="connectString" value="MicroSoft"/>
    </bean>

ObScenityRemovingBeanFactoryPostProcessor.java

public class ObScenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    private Set<String> obscenties;

    public ObScenityRemovingBeanFactoryPostProcessor() {
        this.obscenties = new HashSet<>();
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String [] beanNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            StringValueResolver stringValueResolver = strVal -> {
                if (isObscene(strVal)) {
                    return "*****";
                }
                return strVal;
            };
            BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver);
            visitor.visitBeanDefinition(beanDefinition);
        }
    }

    public boolean isObscene (Object val) {
        String potentialObscenity = val.toString().toUpperCase();
        return this.obscenties.contains(potentialObscenity);
    }

    public void setObscenties(Set<String> obscenties) {
        this.obscenties.clear();
        for (String obscenity : obscenties) {
            this.obscenties.add(obscenity.toUpperCase());
        }
    }
}

测试类

    @Test
    public void testObscenityPostProcessor() {
        ConfigurableListableBeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));
        BeanFactoryPostProcessor beanFactoryPostProcessor = (BeanFactoryPostProcessor) bf.getBean("bfpp");
        beanFactoryPostProcessor.postProcessBeanFactory(bf);
        System.out.println(bf.getBean("simple"));
    }

输出结果

SimplePostProcessor{connectString='*****', password='*****', username='imaginecup'}

通过自定义的 BeanFactoryPostProcessor Spring 很好的实现了屏蔽掉 obscenties 定义的不应该展示的属性。

  1. 激活 BeanFactoryPostProcessor

    上面了解了 BeanFactoryPostProcessor 的用法之后我们在深入研究其调用过程。

public static void invokeBeanFactoryPostProcessors(
         ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

     // Invoke BeanDefinitionRegistryPostProcessors first, if any.
     Set<String> processedBeans = new HashSet<String>();
         // 对 BeanDefinitionRegistry 类型的处理
     if (beanFactory instanceof BeanDefinitionRegistry) {
         BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
         List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
         List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
         // 硬编码注册的后处理器
         for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
             if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                 BeanDefinitionRegistryPostProcessor registryProcessor =
                         (BeanDefinitionRegistryPostProcessor) postProcessor;
                      // 对于BeanDefinitionRegistryPostProcessor类型的,在BeanFactoryPostProcessor的基础上还有自己定义的方法,需要先调用
                 registryProcessor.postProcessBeanDefinitionRegistry(registry);
                 registryProcessors.add(registryProcessor);
             }
             else {
                      // 记录常规的BeanFactoryPostProcessor
                 regularPostProcessors.add(postProcessor);
             }
         }

         // Do not initialize FactoryBeans here: We need to leave all regular beans
         // uninitialized to let the bean factory post-processors apply to them!
         // Separate between BeanDefinitionRegistryPostProcessors that implement
         // PriorityOrdered, Ordered, and the rest.
         List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

         // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
             // 配置注册的后置处理器
         String[] postProcessorNames =
                 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
                  // 先调用实现了PriorityOrdered 接口的
             if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                 processedBeans.add(ppName);
             }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
             // BeanDefinitionRegistryPostProcessor的特殊处理
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();

         // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
                  // 接下来调用 实现了Ordered 接口的
             if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                 processedBeans.add(ppName);
             }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();

         // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
         boolean reiterate = true;
         while (reiterate) {
             reiterate = false;
             postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
             for (String ppName : postProcessorNames) {
                      // 处理剩余的BeanDefinitionRegistryPostProcessors,直到没有
                 if (!processedBeans.contains(ppName)) {
                     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                     processedBeans.add(ppName);
                     reiterate = true;
                 }
             }
             sortPostProcessors(currentRegistryProcessors, beanFactory);
             registryProcessors.addAll(currentRegistryProcessors);
             invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
             currentRegistryProcessors.clear();
         }

         // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
             // 激活BeanDefinitionRegistryPostProcessor的postProcessBeanFactory,之前激活的是postProcessBeanDefinitionRegistry
         invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
             // 激活硬编码注册的常规postProcessors
         invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
     }

     else {
         // Invoke factory processors registered with the context instance.
             // bean工厂非BeanDefinitionRegistry,激活硬编码的beanFactoryPostProcessors
         invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
     }

     // Do not initialize FactoryBeans here: We need to leave all regular beans
     // uninitialized to let the bean factory post-processors apply to them!
         // 对于配置中读取的BeanFactoryPostProcessor的处理
     String[] postProcessorNames =
             beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

     // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
     // Ordered, and the rest.
     List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
     List<String> orderedPostProcessorNames = new ArrayList<String>();
     List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
      // 对后置处理器进行分类
     for (String ppName : postProcessorNames) {
         if (processedBeans.contains(ppName)) {
             // skip - already processed in first phase above 上面第一步已经处理
         }
         else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
             priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
         }
         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
             orderedPostProcessorNames.add(ppName);
         }
         else {
             nonOrderedPostProcessorNames.add(ppName);
         }
     }

     // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
         // 对于实现PriorityOrdered接口的 按照优先级进行排序
     sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
     invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

     // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
         // 按照order进行排序
     List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
     for (String postProcessorName : orderedPostProcessorNames) {
         orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
     }
     sortPostProcessors(orderedPostProcessors, beanFactory);
     invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

     // Finally, invoke all other BeanFactoryPostProcessors.
     List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
     for (String postProcessorName : nonOrderedPostProcessorNames) {
         nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
     }
         // 无序,直接调用
     invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

     // Clear cached merged bean definitions since the post-processors might have
     // modified the original metadata, e.g. replacing placeholders in values...
     beanFactory.clearMetadataCache();
 }

从上面的方法中我们发现,对于 BeanFactoryPostProcessor 的处理分为两种情况进行:

一种是 ConfigurableListableBeanFactory 属于 BeanDefinitionRegistry ,则需要处理 BeanDefinitionRegistryPostProcessor,另外一种是 beanFactory 不属于 BeanDefinitionRegistry 则只需要处理 BeanFactoryPostProcessor。而对于这两种情况 则都需要考虑硬编码注册的后置处理器以及通过配置注册的后置处理器。

这里我们一起看下 BeanDefinitionRegistry 类型的处理过程,因为非BeanDefinitionRegistry 类型的只需要进行普通BeanFactoryPostProcessor 的处理。

(1)对于硬编码注册的后置处理器,主要是通过 AbstractApplicationContext 中添加后置处理器的方法 addBeanFactoryPostProcessor 进行添加:

 public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
     Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
     this.beanFactoryPostProcessors.add(postProcessor);
 }

添加的后处理器被放在beanFactoryPostProcessors 中,而在调用处理 BeanFactoryPostProcessor 时会判断beanFactoryPostProcessors 是否有数据。由于 BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor ,因此它不但有 BeanFactoryPostProcessor 的特性同时还有自定义的个性化方法,所以这里需要从beanFactoryPostProcessors 中过滤出BeanDefinitionRegistryPostProcessor 类型的后处理器,进行其个性化方法 postProcessBeanDefinitionRegistry 的调用。

(2)记录后处理器使用了两个List。 registryProcessors 记录 BeanDefinitionRegistryPostProcessor 这种特殊的后处理器,regularPostProcessors 记录通过硬编码注册的BeanFactoryPostProcessor 类型的处理器。

(3) 将通过配置注册的 BeanDefinitionRegistryPostProcessor 按照优先级排序并调用postProcessBeanDefinitionRegistry 然后加入到registryProcessors 这个List中。对于这两个List进行统一的调用 BeanFactoryPostProcessor 类的 postProcessBeanFactory方法。

(4) 通过配置注册的普通BeanFactoryPostProcessor 处理。和BeanDefinitionRegistryPostProcessor 处理流程类似。

BeanDefinitionRegistryPostProcessor 只对 BeanDefinitionRegistry 类型的beanFactory有效,所以如果 beanFactory 并不是 BeanDefinitionRegistry 类型,则只需要处理 BeanFactoryPostProcessor ,包括硬编码注册和配置注册的后处理器。

认真看的同学会发现,对于硬编码方法注册的 BeanFactoryPostProcessor 不需要作任何排序,但是在配置文件中读取的处理器,Spring并不会保证读取的顺序。所以为了保证用户的调用顺序的要求,Spring对于后处理器的调用支持按照PriorityOrdered 或者Ordered的调用顺序。

注册BeanPostProcessor

​ 上面我们提到了 BeanFactoryPostProcessor 的调用,这一节我们学习 BeanPostProcessor ,但是这里并不是调用而是注册。真正的调用其实是在 bean 的实例化阶段。这是一个很重要的步骤,由于不调用后处理器导致很多功能 BeanFactory 不支持。

​ 下面我们继续探讨 registerBeanPostProcessors 的方法实现。

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
        List<String> orderedPostProcessorNames = new ArrayList<String>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // Next, register the BeanPostProcessors that implement Ordered.
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // Now, register all regular BeanPostProcessors.
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // Finally, re-register all internal BeanPostProcessors.
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

BeanFactoryPostProcessor 和 BeanPostProcessor 两者之间区别不大,感兴趣的可以再看下上面代码,相信不难看懂。

初始化消息资源

这里主要进行国际化处理,即常见的多语言app,需要按照客户端的语言返回不同的页面 。 Spring 定义了访问国际化信息的 MessageSource 接口,并提供了几个易用的实现类。 Message 接口分别被 HierarchicalMessageSource 和ApplicationContext 接口扩展。

    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // Make MessageSource aware of parent MessageSource.
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // Only set parent context as parent MessageSource if no parent MessageSource
                    // registered already.
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // Use empty MessageSource to be able to accept getMessage calls.
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                        "': using default [" + this.messageSource + "]");
            }
        }
    }

初始化ApplicationEventMulticaster

​ 在开始研究 Spring 的时间传播器之前,我们先来看一个 Spring 的事件监听的简单用法。

  1. 定义监听事件。

    public class TestEvent extends ApplicationEvent{
    
        public String msg;
    
        /**
         * Create a new ApplicationEvent.
         *
         * @param source the object on which the event initially occurred (never {@code null})
         */
        public TestEvent(Object source) {
            super(source);
        }
    
        public TestEvent(Object source,String msg) {
            super(source);
            this.msg = msg;
        }
    
        public void print() {
            System.out.println(msg);
        }
    }
    
  1. 定义监听器

    public class TestListener implements ApplicationListener{
    
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof TestEvent) {
                TestEvent testEvent = (TestEvent) event;
                testEvent.print();
            }
        }
    }
    
  2. 添加配置文件

    <bean id="testListener" class="com.ccgogoing.listener.TestListener"/>
    
  1. 测试

        @Test
        public void testEvent() {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            TestEvent testEvent = new TestEvent("hello","msg");
            applicationContext.publishEvent(testEvent);
        }
    

当程序运行时,Spring 会将发出的 TestEvent 事件转给我自定义的 TestLinstener 进行进一步处理。

相信很多人看到这里,一下子会想到了观察者模式,这确实是个典型的应用,可以在比较关心的事件结束后及时进行处理。那么我们接下来一起看看 ApplicationEventMulticaster 是如何被初始化的,以确保功能的正确运行。

initApplicationEventMulticaster 的方式比较简单,无非考虑两种情况。

  • 如果用户自定义了事件广播器则使用自定义的广播器。
  • 如果用户没有自定义的事件广播器,则使用默认的 ApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }

按照之前我们了解的事件监听的顺序和逻辑,我们推断,作为广播器,一定是用于存放监听器并在合适的时候调用监听器,那么我们不妨进入默认的广播器实现 SimpleApplicationEventMulticaster 来一探究竟。

下面这段代码是关键所在:

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        invokeListener(listener, event);
                    }
                });
            }
            else {
                invokeListener(listener, event);
            }
        }
    }

可以看到,当产生Spring 事件的时候会默认使用 SimpleApplicationEventMulticaster 的 multicastEvent 方法来广播事件,遍历所有监听器,并使用监听器中的 onApplicationEvent 方法来进行监听器处理。

注册监听器

​ 上面在学习 Spring 广播器的时候反复提到了事件监听器,那么在 Spring注册监听器的时候又做了哪些逻辑操作呢?

protected void registerListeners() {
        // Register statically specified listeners first.
         // 硬编码方式注册的监听器处理
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        // 配置文件注册的监听器处理
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // Publish early application events now that we finally have a multicaster...
        // 由于上一步初始化了广播器,那么就开始派发早期的事件吧
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

初始化非延迟加载单例

​ 完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置、配置冻结 以及 非延迟加载的 bean 的初始化工作。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
                @Override
                public String resolveStringValue(String strVal) {
                    return getEnvironment().resolvePlaceholders(strVal);
                }
            });
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        // 冻结所有 bean 定义,说明注册的bean定义将不被修改或任何进一步的处理
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        // 初始化剩下的所有非延迟加载的单实例bean
        beanFactory.preInstantiateSingletons();
    }

  1. ConversionService 的设置

    Spring提供了一种类型转换方式:使用converter,比如将String 转换为 Date。下面我们使用一个简单的示例来了解下 Converter 的使用方式。

    (1) 定义转换器

    public class String2DateConverter implements Converter<String,Date> {
        @Override
        public Date convert(String source) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = sdf.parse(source);
                return date;
            } catch (Exception e) {
                return null;
            }
        }
    }
    

    (2) 注册

        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <list>
                    <bean class="com.ccgogoing.domain.String2DateConverter"/>
                </list>
            </property>
        </bean>
    

    (3) 测试

         @Test
        public void testString2DateConvert() {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            DefaultConversionService conversionService = (DefaultConversionService) applicationContext.getBean("conversionService");
            conversionService.addConverter(new String2DateConverter());
            String dateStr = "2019-02-21";
            Date date = conversionService.convert(dateStr,Date.class);
            System.out.println(date);
        }
    
    

    通过以上功能我们看到了 Converter 和 ConversionService 提供的便利功能,其中的配置就是在当前函数中初始化的。

  1. 冻结配置

    冻结所有bean的定义,说明注册的bean定义将不再做任何修改或进行任何一进步的处理。

     @Override
     public void freezeConfiguration() {
         this.configurationFrozen = true;
         this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
     }
    
  1. 初始化非延迟加载

    ApplicationContext 实现的默认行为就是在启动时将所有的单例 bean 提前实例化。 提前实例化意味着作为初始化过程的一部分, ApplicationContext 实例会创建并配置所有的单例 bean。通常情况下这是一件好事,因为这样在配置中的任何错误就会被即刻发现(否则可能要花几个小时甚至几天)。 而这个实例化的过程就是在 preInstantiateSingletons 中完成的。

    @Override
     public void preInstantiateSingletons() throws BeansException {
         if (this.logger.isDebugEnabled()) {
             this.logger.debug("Pre-instantiating singletons in " + this);
         }
    
         // Iterate over a copy to allow for init methods which in turn register new bean definitions.
         // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
         List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    
         // Trigger initialization of all non-lazy singleton beans...
         for (String beanName : beanNames) {
             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                 if (isFactoryBean(beanName)) {
                     final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                     boolean isEagerInit;
                     if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                         isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                             @Override
                             public Boolean run() {
                                 return ((SmartFactoryBean<?>) factory).isEagerInit();
                             }
                         }, getAccessControlContext());
                     }
                     else {
                         isEagerInit = (factory instanceof SmartFactoryBean &&
                                 ((SmartFactoryBean<?>) factory).isEagerInit());
                     }
                     if (isEagerInit) {
                         getBean(beanName);
                     }
                 }
                 else {
                     getBean(beanName);
                 }
             }
         }
    
         // Trigger post-initialization callback for all applicable beans...
         for (String beanName : beanNames) {
             Object singletonInstance = getSingleton(beanName);
             if (singletonInstance instanceof SmartInitializingSingleton) {
                 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                 if (System.getSecurityManager() != null) {
                     AccessController.doPrivileged(new PrivilegedAction<Object>() {
                         @Override
                         public Object run() {
                             smartSingleton.afterSingletonsInstantiated();
                             return null;
                         }
                     }, getAccessControlContext());
                 }
                 else {
                     smartSingleton.afterSingletonsInstantiated();
                 }
             }
         }
     }
    

finishRefresh

​ 在 Spring 中提供了 LifeCycle 接口, LifeCycle 中包含start/stop 方法,实现此接口后Spring 会保证在启动的时候调用 start 方法开始生命周期,并在 Spring 关闭的时候调用 stop 方法来结束生命周期,通常用来配置后台程序,再启动后一直运行(如对MQ进行轮询等)。而 ApplicationContext 的初始化最后正是保证了这一功能的实现。

    protected void finishRefresh() {
        // Initialize lifecycle processor for this context.
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }
  1. initLifecycleProcessor

    当ApplicationContext 启动或停止时,它会通过LifeCycleProcessor来与所有生命的 bean 的周期做状态更新,而在LifeCycleProcessor 的使用前首先需要进行初始化。

protected void initLifecycleProcessor() {
     ConfigurableListableBeanFactory beanFactory = getBeanFactory();
     if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
         this.lifecycleProcessor =
                 beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
         if (logger.isDebugEnabled()) {
             logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
         }
     }
     else {
         DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
         defaultProcessor.setBeanFactory(beanFactory);
         this.lifecycleProcessor = defaultProcessor;
         beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
         if (logger.isDebugEnabled()) {
             logger.debug("Unable to locate LifecycleProcessor with name '" +
                     LIFECYCLE_PROCESSOR_BEAN_NAME +
                     "': using default [" + this.lifecycleProcessor + "]");
         }
     }
 }
  1. OnRefresh

    启动所有实现了 LifeCycle 接口的 bean。

 @Override
 public void onRefresh() {
     startBeans(true);
     this.running = true;
 }
 
 
 private void startBeans(boolean autoStartupOnly) {
     Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
     Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
     for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
         Lifecycle bean = entry.getValue();
         if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
             int phase = getPhase(bean);
             LifecycleGroup group = phases.get(phase);
             if (group == null) {
                 group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                 phases.put(phase, group);
             }
             group.add(entry.getKey(), bean);
         }
     }
     if (!phases.isEmpty()) {
         List<Integer> keys = new ArrayList<Integer>(phases.keySet());
         Collections.sort(keys);
         for (Integer key : keys) {
             phases.get(key).start();
         }
     }
 }
  1. publishEvent

    当完成ApplicationContext初始化的时候,要通过 Spring 中的事件发布机制来发布 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理。

protected void publishEvent(Object event, ResolvableType eventType) {
     Assert.notNull(event, "Event must not be null");
     if (logger.isTraceEnabled()) {
         logger.trace("Publishing event in " + getDisplayName() + ": " + event);
     }

     // Decorate event as an ApplicationEvent if necessary
     ApplicationEvent applicationEvent;
     if (event instanceof ApplicationEvent) {
         applicationEvent = (ApplicationEvent) event;
     }
     else {
         applicationEvent = new PayloadApplicationEvent<Object>(this, event);
         if (eventType == null) {
             eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
         }
     }

     // Multicast right now if possible - or lazily once the multicaster is initialized
     if (this.earlyApplicationEvents != null) {
         this.earlyApplicationEvents.add(applicationEvent);
     }
     else {
         getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
     }

     // Publish event via parent context as well...
     if (this.parent != null) {
         if (this.parent instanceof AbstractApplicationContext) {
             ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
         }
         else {
             this.parent.publishEvent(event);
         }
     }
 }

至此,Spring 容器就启动完毕了,相信大家仔细看完这两篇文章一定会对 Spring 的原理有更进一步的了解。

传送门:

《Spring容器的基本实现之源码分析-上篇》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,921评论 4 21
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,669评论 0 11
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,782评论 1 24
  • “林余为了爱跳楼自杀了。” “?” “扯蛋呢?” “真的,就在今天早上十点左右的时候。” “他妈的,他赌神经病了?...
    拾荒者指纹阅读 311评论 0 0
  • 给我们阳光,给我们美好 你让所有少女在云端舞蹈歌唱 给我们时间,让我们衰老 你看死亡的鱼骨架,催生出腐朽 给我们光...
    葵花宝殿阅读 143评论 0 0