Spring源码解析:高级容器的扩展内幕

栏目: Java · 发布时间: 6年前

内容简介:Spring源码解析:高级容器的扩展内幕

前面我们一直在以 BeanFactory 作为出发点探究容器的初始化和注入过程,不过 Spring 为我们提供了更加高级的接口 ApplicationContext 可供使用,这也是官方推荐的使用方式。ApplicationContext 相对于 BeanFactory 扩展了许多实用功能,方便开发者的使用,二者的结构设计我们也在前面的文章中进行了专门的讲解,本篇我们一起来详细探究一下基于 ApplicationContext 的容器初始化和注入过程,至于 ApplicationContext 的使用方式,广大开发者应该是信手拈来,这里还是简单的举例一下:

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-core.xml");
MyBean myBean = (MyBean) context.getBean("my-bean");
myBean.sayHello();

相对于 BeanFactory 来说,使用方式上没有太大的区别,也是分成两步走,第一步加载配置,第二步执行 bean 实例的创建和初始化过程。其中第二步与之前我们探究 BeanFactory 时的 getBean 方法复用的是一套逻辑,因为由前面文章的继承关系我们已经知道 ApplicationContext 不是一个新的策略实现类,而是从 BeanFactory 扩展而来,并且将主要的精力都放在了对于配置文件加载的扩展上,这样的实现也是很容易理解的,毕竟第一步是和开发者息息相关的,是开发者能够直观配置的东西,这一块的优化能够直观反映在框架的使用上,而第二步主要是框架内部的事情,所以接下来我们主要探究第一步的实现过程,而第二步则可以参考前面专门讲解 Bean 实例创建与初始化过程的文章。

第一步的逻辑暴露给开发者的接口位于 ClassPathXmlApplicationContext 的构造方法中,我们通过 new ClassPathXmlApplicationContext("classpath:spring-core.xml") 来触发容器执行配置加载的逻辑:

public ClassPathXmlApplicationContext(String configLocation)throwsBeansException{
    this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations,booleanrefresh, ApplicationContext parent)throwsBeansException{
    super(parent);
    // 支持多个配置文件以数组形式传入
    this.setConfigLocations(configLocations);
    if (refresh) {
        // refresh方法几乎包含了ApplicationContext的全部功能
        this.refresh();
    }
}

方法第一步需要记录传递的配置文件路径,因为可以同时传递多个配置文件,并且配置文件的组织形式不一定是容器能够理解的方式,所以还需要执行一些解析的工作:

public void setConfigLocations(String... locations){
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            // 解析给定的路径,将占位符替换成具体的值
            this.configLocations[i] = this.resolvePath(locations[i]).trim();
        }
    } else {
        this.configLocations = null;
    }
}

我们传递的配置文件可能存在一些占位符来代替一些变量,所以在上述方法中容器需要对这些变量进行解析,并用真实指代的值进行替换,最终将路径记录到实例字符串数组变量 configLocations 中。

接下来需要调用 refresh 方法,该方法是 ApplicationContext 的核心,可以看做是对 ApplicationContext 功能的一个总调度器:

public void refresh()throwsBeansException, IllegalStateException{
    synchronized (this.startupShutdownMonitor) {
        // 1. 初始化 refresh 的上下文环境
        this.prepareRefresh();

        // 2. 初始化 BeanFactory,加载并解析配置
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

        /* ---至此,完成了简单容器的所有功能,下面开始对简单容器进行增强--- */

        // 3. 对 BeanFactory 进行功能增强
        this.prepareBeanFactory(beanFactory);

        try {
            // 4. 后置处理 beanFactory,交由子类实现
            this.postProcessBeanFactory(beanFactory);

            // 5. 调用已注册的 BeanFactoryPostProcessor
            this.invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册 BeanPostProcessor,仅仅是注册,调用在getBean的时候
            this.registerBeanPostProcessors(beanFactory);

            // 7. 初始化国际化资源
            this.initMessageSource();

            // 8. 初始化事件广播器
            this.initApplicationEventMulticaster();

            // 9. 留给子类实现的模板方法
            this.onRefresh();

            // 10. 注册事件监听器
            this.registerListeners();

            // 11. 实例化所有非延迟加载的单例
            this.finishBeanFactoryInitialization(beanFactory);

            // 12. 完成刷新过程,发布应用事件
            this.finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
            }
            // Destroy already created singletons to avoid dangling resources.
            this.destroyBeans();
            // Reset 'active' flag.
            this.cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            this.resetCommonCaches();
        }
    }
}

我们先来概括一下整个方法的执行过程,然后再来逐个过程展开细说:

  1. 初始化 refresh 的上下文环境
  2. 初始化 BeanFactory,加载并解析配置
  3. 对 BeanFactory 进行功能增强
  4. 后置处理器 BeanFactory
  5. 调用已注册的 BeanFactoryPostProcessor
  6. 注册各个 BeanPostProcessor
  7. 初始化国际化资源
  8. 初始化事件广播器
  9. 注册事件监听器
  10. 实例化所有非延迟加载的单例
  11. 完成刷新过程,发布应用事件

上述过程中到第 2 步为止已经完成了简单容器中解析配置文件,以 BeanDefinition 进行容器内表示的全部过程,从第 3 步开始均是属于高级容器的扩展实现。

1. 初始化 refresh 的上下文环境

方法的第一步就是对刷新需要的上下文环境执行一个初始化操作,这其中包含一些标记变量的赋值和一些属性值的处理工作:

protected void prepareRefresh(){
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // 初始化属性,留给子类覆盖实现
    this.initPropertySources();

    // 验证必要属性是否都已经被解析
    // see ConfigurablePropertyResolver#setRequiredProperties
    this.getEnvironment().validateRequiredProperties();

    // 存放需要提前感知的应用事件
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

Spring 在这里提供了供子类覆盖实现的模板方法 initPropertySources,从而可以让子类拥有修改属性的机会。一些属性对于系统来说是必要的,缺失则会影响系统的正常逻辑,对于这类属性我们可以调用 setRequiredProperties 方法将其设置为 “required”,这样在本方法中就会验证其是否存在,如果不存在则会提前抛出异常。

2. 初始化 BeanFactory,加载并解析配置

本步骤中包含了加载和解析配置文件的复杂逻辑,并返回创建的 ConfigurableListableBeanFactory 对象,前面我们曾强调过 ConfigurableListableBeanFactory 在 BeanFactory 的继承体系中占有着相当重要的地位,它是包含容器完整功能的一个基本实现。

protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){
    // 1. 初始化BeanFactory,并执行加载和解析配置操作,在这一步已经得到了beanDefinition实例
    this.refreshBeanFactory();
    // 2. 返回beanFactory实例
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

上述方法的逻辑就是创建 beanFactory 对象并返回,refreshBeanFactory 是整个方法的核心:

protected final void refreshBeanFactory()throwsBeansException{
    // 存在beanFactory
    if (this.hasBeanFactory()) {
        // 注销所有的单例
        this.destroyBeans();
        // 重置beanFactory
        this.closeBeanFactory();
    }
    try {
        // 创建DefaultListableBeanFactory对象,DefaultListableBeanFactory是容器的基本实现
        DefaultListableBeanFactory beanFactory = this.createBeanFactory();
        // 指定序列化id,必要的话可以反序列化得到beanFactory对象
        beanFactory.setSerializationId(this.getId());
        /*
         * 1. 是否允许配置同名称的bean(后面的配置会覆盖前面的配置)
         * 2. 是否允许循环依赖
         */
        this.customizeBeanFactory(beanFactory);
        // 加载并解析xml配置,由静态配置转为beanDefinition
        this.loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    } catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

方法中首先会判断是否已经有创建的 beanFactory 实例存在,有的话则重置,然后重新创建 beanFactory 对象,创建的过程中会执行 loadBeanDefinitions 逻辑,如果看过本系列之前的文章,一定会理解本方法的作用并且体会到其过程的复杂程度,该方法包含了获取配置文件 Document 对象,并执行默认标签和自定义标签的解析,将配置封装到 beanDefinition 对象中返回的逻辑,经过这一步骤,xml 中静态的配置文件就会转变成内存中的数据结构存放于容器中。

3. 对 BeanFactory 进行功能增强

前面两个步骤已经完成了简单容器的全部功能,从这里开始将对简单容器进行扩展增强处理。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory){
    // 设置使用上下文的类加载器
    beanFactory.setBeanClassLoader(this.getClassLoader());
    // 设置表达式解析器以提供EL表达式风格的属性调用(3.0版本引入)
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 增加默认属性编辑器
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    /*
     * 添加后置处理器ApplicationContextAwareProcessor, 如果实现了相应的 Aware 接口,则注入对应的资源
     * 1. EnvironmentAware
     * 2. EmbeddedValueResolverAware
     * 3. ResourceLoaderAware
     * 4. ApplicationEventPublisherAware
     * 5. MessageSourceAware
     * 6. ApplicationContextAware
     */
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 忽略以下接口的自动装配,对应上一行代码中处理的接口
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 注册几个自动装配的规则
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 注册后置处理器 ApplicationListenerDetector,用于探测 ApplicationListener 类型接口
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 增加对 AspectJ 的支持
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认系统环境相关的bean
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        // Environment
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        // System Properties
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        // System Environment
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

prepareBeanFactory 方法对 BeanFactory 的功能增强主要包括:

  1. 增加了对 Spring 表达式(SpEL)的支持。
  2. 增加了对属性编辑器的支持。
  3. 增加了对一些 Aware 类的自动装配支持。
  4. 增加了对 ApplicationListener 类型 bean 的发现支持。
  5. 增加了对 AspectJ 的支持。
  6. 注册了几个系统环境变量相关的 bean。

Spring Expression Language(SpEL)是在 3.0 版本引入的新特性,允许我们在配置时候以类似 EL 表达式的方式去引用上下文中的变量,未接触过的同学可以自己去体验一下,笔者用的也不是很多。

在配置 bean 的时候,如果我们希望对某一类型的属性执行一些处理,可以通过自定义属性编辑器来实现,典型的应用场景就是对时间类型属性的转换,假设我们的 bean 存在 LocalDate 类型的属性,这个时候我们直接以字符串配置进行注入是会出现异常的,这个时候我们可以自定义属性编辑器来实现类型的转换:

public class MyDatePropertyEditorextends PropertyEditorSupportimplements InitializingBean{

    private String format = "yyyy-MM-dd";

    private DateTimeFormatter dtf;

    @Override
    public void afterPropertiesSet()throwsException{
        dtf = DateTimeFormatter.ofPattern(format);
    }

    @Override
    public void setAsText(String text)throwsIllegalArgumentException{
        if (!StringUtils.hasText(text)) {
            this.setValue(null);
            return;
        }
        this.setValue(LocalDate.parse(text));
    }

    publicMyDatePropertyEditorsetFormat(String format){
        this.format = format;
        return this;
    }
}
<!--注册自定义属性解析器-->
<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <propertyname="customEditors">
        <map>
            <entrykey="java.time.LocalDate">
                <beanclass="org.zhenchao.editor.MyDatePropertyEditor">
                    <propertyname="format"value="yyyy-MM-dd"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>

我们自定义的属性编辑器 MyDatePropertyEditor 通过时间格式化 工具 对指定模式的字符串格式日期执行转换和注入,而上述转换只能在我们以 ApplicationContext 的方式加载 bean 的前提下才生效,如果我们以 BeanFactory 的方式加载 bean,还是会抛出异常,毕竟这属于高级容器中增强的功能。

当我们定义的 bean 实现了 Aware 接口的时候,我们总能比一般的 bean 多拿到一些资源,而此处对于 beanFactory 的扩展也增加了对一些 Aware 类自动装配的支持。ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,并主要实现了 postProcessBeforeInitialization 逻辑:

publicObjectpostProcessBeforeInitialization(finalObject bean, String beanName)throwsBeansException{
    AccessControlContext acc = null;

    if (System.getSecurityManager() != null &&
            (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                    bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                    bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
        acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    }

    if (acc != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            publicObjectrun(){
                invokeAwareInterfaces(bean);
                return null;
            }
        }, acc);
    } else {
        // 核心在于激活 Aware
        this.invokeAwareInterfaces(bean);
    }

    return bean;
}

上述方法的核心在于 invokeAwareInterfaces 方法:

private void invokeAwareInterfaces(Object bean){
    if (bean instanceof Aware) {
        // EnvironmentAware
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        // EmbeddedValueResolverAware
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        // ResourceLoaderAware
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        // ApplicationEventPublisherAware
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        // MessageSourceAware
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        // ApplicationContextAware
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }
}

整个方法的逻辑很直观,判断当前类所实现的 Aware 接口,然后将相应的资源给到该 bean,以 ApplicationContextAware 举例来说,实现了该接口的 bean 都持有 ApplicationContext 的实例,而上述方法也正是调用了相应的 setter 将 ApplicationContext 实例注入到 bean 实例中。

在 4.3.x 版本中增加了对实现了 ApplicationListener 接口的探测,ApplicationListenerDetector 实现了 MergedBeanDefinitionPostProcessor 和 DestructionAwareBeanPostProcessor 后置处理接口,并相应实现了这些后置处理器定义的模板方法,其中核心的方法 postProcessAfterInitialization 逻辑如下:

publicObjectpostProcessAfterInitialization(Object bean, String beanName){
    if (this.applicationContext != null && bean instanceof ApplicationListener) {
        // 实现了 ApplicationListener 接口
        Boolean flag = this.singletonNames.get(beanName);
        if (Boolean.TRUE.equals(flag)) { // 单例
            this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
        } else if (Boolean.FALSE.equals(flag)) { // 非单例
            if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                // inner bean with other scope - can't reliably process events
                logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext " +
                        "because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.");
            }
            this.singletonNames.remove(beanName);
        }
    }
    return bean;
}

该方法针对实现了 ApplicationListener 接口的单例,统一注册到监听器集合中监听事件,而方法中的 singletonNames 变量则是在 postProcessMergedBeanDefinition 方法中进行构建:

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName){
    if (this.applicationContext != null) {
        this.singletonNames.put(beanName, beanDefinition.isSingleton());
    }
}

由此我们可以知道 singletonNames 中存放了 beanName,以及对应的 bean 是否是单例的关联关系。

4. 后置处理器 BeanFactory

refresh 中设置一个用于处理 BeanFactory 的模板方法:postProcessBeanFactory(beanFactory)。该方法的实现逻辑交由子类,用于增强 Spring 框架的可扩展性。

5. 调用已注册的 BeanFactoryPostProcessor 后置处理器

BeanFactoryPostProcessor 用于对 BeanFactory 实例进行后置处理,这和 BeanPostProcessor 以 bean 实例作为处理对象有着本质的区别,所以说代码执行到这里就已经开始激活这些已经注册的 BeanFactoryPostProcessor 后置处理器处理前面已经准备好的 BeanFactory 对象,但是需要清楚的是这个时候还没有开始创建 bean 实例。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){
    // 激活 BeanFactoryPostProcessor 后置处理器
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
    // AOP支持:LoadTimeWeaver
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

注意这里传入的 this.getBeanFactoryPostProcessors() 参数全部是编码注册的 BeanFactoryPostProcessor 通过调用如下方法进行添加:

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

笔者最开始看这段代码的时候,潜意识认为所有的 BeanFactoryPostProcessor 都是记录在 beanFactoryPostProcessors 代码段中的,如果以配置的方式使用过 BeanFactoryPostProcessor 的同学都知道,BeanFactoryPostProcessor 的配置仅仅需要在配置文件中配置一个 bean,比如:

<beanid="myBeanFactoryPostProcessor"class="org.zhenchao.processor.MyBeanFactoryPostProcessor"/>

我们不需要在其它任何地方去注册或引用 myBeanFactoryPostProcessor,所以我就去代码中探究 Spring 是如何把上述配置给添加到 beanFactoryPostProcessors 中的,即在哪里调用了 addBeanFactoryPostProcessor 方法,结果一无所获,因为出发点就是错误的,下面的源码中你将看到这里传递的仅仅是编码注册的 BeanFactoryPostProcessor,而配置的方式通过其他的方式获取到的:

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

    /*beanFactoryPostProcessors 保存了所有通过编码注册的 BeanFactoryPostProcessor*/

    Set<String> processedBeans = new HashSet<String>();
    // 如果是 BeanDefinitionRegistry 类型
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); // 记录注册的 BeanFactoryPostProcessor 类型处理器
        List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 记录注册的 BeanDefinitionRegistryPostProcessor 类型处理器

        // 一. 遍历处理编码注册的 BeanFactoryPostProcessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                /*
                 * 如果是 BeanDefinitionRegistryPostProcessor (继承自 BeanFactoryPostProcessor)
                 * 1. 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法 postProcessBeanDefinitionRegistry
                 * 2. 记录到 registryPostProcessors 集合中,用于后面处理继承自 BeanFactoryPostProcessor 的方法
                 */
                BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                registryPostProcessors.add(registryPostProcessor);
            } else {
                // 否则就是 BeanFactoryPostProcessor
                regularPostProcessors.add(postProcessor);
            }
        }

        // 二. 获取配置的 BeanDefinitionRegistryPostProcessor 类型后置处理器
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

        /* 1.激活所有实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor */
        List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 对处理器进行排序
        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
        registryPostProcessors.addAll(priorityOrderedPostProcessors);
        // 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
        invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

        /* 2.激活所有实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor */
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 对处理器进行排序
        sortPostProcessors(beanFactory, orderedPostProcessors);
        registryPostProcessors.addAll(orderedPostProcessors);
        // 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
        invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);

        /* 3.激活剩余的 BeanDefinitionRegistryPostProcessor */
        boolean reiterate = true;  // 反复的
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) { // 没有处理过的
                    BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
                    registryPostProcessors.add(pp);
                    processedBeans.add(ppName);
                    // 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
                    pp.postProcessBeanDefinitionRegistry(registry);
                    reiterate = true;
                }
            }
        }

        // 激活所有 BeanDefinitionRegistryPostProcessor 后置处理器中的 postProcessBeanFactory 方法
        invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
        // 激活所有 BeanFactoryPostProcessor 后置处理器中的 postProcessBeanFactory 方法
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // 如果不是 BeanDefinitionRegistry 类型,直接激活所有编码注册的 BeanFactoryPostProcessor 后置处理器
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 获取配置的 BeanFactoryPostProcessor 类型后置处理器
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    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)) {
            // 跳过已经处理过的 bean
        } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 实现了 PriorityOrdered 接口
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 实现了 Ordered 接口
            orderedPostProcessorNames.add(ppName);
        } else {
            // 其它
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    /* 1.激活所有实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor */
    sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    /* 2.激活所有实现了 Ordered 接口的 BeanFactoryPostProcessor */
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(beanFactory, orderedPostProcessors);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    /* 3.激活剩余的 BeanFactoryPostProcessor */
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清理工作
    beanFactory.clearMetadataCache();
}

我们可以看到针对编码注册和以配置方式注册的 BeanFactoryPostProcessor,Spring 的获取方式是不一样的,前者都是注册到前面所说的 beanFactoryPostProcessors 集合中,而后者都是通过 BeanFactory 的 getBeanNamesForType 方法获取到的。

上述方法先判断 BeanFactory 是不是 BeanDefinitionRegistry 类型,如果是的话则专门处理,这样设计是因为继承自 BeanFactoryPostProcessor 的 BeanDefinitionRegistryPostProcessor 需要专门处理这种类型:

public interface BeanDefinitionRegistryPostProcessorextends BeanFactoryPostProcessor{

    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)throwsBeansException;

}

并且针对配置的 BeanFactoryPostProcessor 而言,因为获取顺序的不确定性,所以 Spring 支持对其配置优先级,上述方法的逻辑也可以看出 Spring 会依次处理 PriorityOrdered、Ordered,以及其他类型,并会针对各类型进行按照比较器进行 排序 处理。

6. 注册 BeanPostProcessor 后置处理器

不同于 BeanFactoryPostProcessor 的调用,这里仅仅是对 BeanPostProcessor 的注册,因为 BeanPostProcessor 作用于 bean 实例之上,而当前还没有开始创建 bean 实例,之前讲解 getBean 过程的文章中我们应该有所记忆,BeanPostProcessor 的调用是发生在 getBean 过程中,具体来说应该是围绕 bean 实例化过程的前后:

public interface BeanPostProcessor{

    ObjectpostProcessBeforeInitialization(Object bean, String beanName)throwsBeansException;

    ObjectpostProcessAfterInitialization(Object bean, String beanName)throwsBeansException;

}

注册过程本质上是将配置的 BeanPostProcessor 添加到 beanPostProcessors 集合的过程,我们在简单容器中需要通过调用 addBeanPostProcessor 编码注册我们实现的 BeanPostProcessor,实际上两者本质上是一样的,只是高级容器支持以配置的方式来完成简单容器中需要编码才能完成的操作:

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

    // 获取配置的 BeanPostProcessor 类型
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // 注册一个 BeanPostProcessorChecker,用于在出现还没有注册后置处理器就开始实例化bean的情况打印日志记录
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); // 存放实现了 PriorityOrdered 接口的 BeanPostProcessor
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); // 存放 MergedBeanDefinitionPostProcessor
    List<String> orderedPostProcessorNames = new ArrayList<String>(); // 存放实现了 Ordered 接口的 BeanPostProcessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); // 存放其它的 BeanPostProcessor

    // 遍历分类
    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);
        }
    }

    // 1.注册实现了 PriorityOrdered 接口的 BeanPostProcessor,不包含 MergedBeanDefinitionPostProcessor
    sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 2.注册实现了 Ordered 接口的 BeanPostProcessor
    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(beanFactory, orderedPostProcessors);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 3.注册其余的除 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
    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);

    // 4.注册所有的 MergedBeanDefinitionPostProcessor
    sortPostProcessors(beanFactory, internalPostProcessors);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // 重新注册 ApplicationListenerDetector,将其移到链尾
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

BeanPostProcessor 与 BeanFactoryPostProcessor 一样,同样支持优先级的配置。

7. 初始化国际化资源

笔者目前所负责的几个项目都需要考虑国际化支持,有的直接基于 jdk 原生的 ResourceBundle,有的则基于 Spring 提供的 MessageSource,在具体分析 MessageSource 的初始化过程之前,我们先来了解一下 Spring 国际化支持的设计与简单使用。

7.1 MessageSource 的设计与简单使用

Spring MessageSource 支持本质上也是对 ResourceBundle 的封装,MessageSource 接口的定义如下:

public interface MessageSource{

    /**
     * 获取指定语言的文案信息
     * code 为属性名称,args 用于传递格式化参数,defaultMessage 表示在找不到指定属性时返回的默认信息,locale 表示本地化对象
     */
    StringgetMessage(String code, Object[] args, String defaultMessage, Locale locale);

    /**
     * 获取指定语言的文案信息
     * 相对于第一个方法的区别在于当找不到对应属性时直接抛出异常
     */
    StringgetMessage(String code, Object[] args, Locale locale)throwsNoSuchMessageException;

    /**
     * 获取指定语言的文案信息
     * 只不过采用 MessageSourceResolvable 来封装第一个方法中的前三个参数
     */
    StringgetMessage(MessageSourceResolvable resolvable, Locale locale)throwsNoSuchMessageException;

}

Spring MessageSource 相关类的继承关系如下:

Spring源码解析:高级容器的扩展内幕

其中 HierarchicalMessageSource 的设计为 MessageSource 提供了层次支持,建立了父子层级结构。ResourceBundleMessageSource 和 ReloadableResourceBundleMessageSource 是我们常用的两个类,均可以看做是对 jdk 原生国际化支持的封装,只不过后者相对于前者提供了定时更新资源文件的支持,从而不需要重启系统。StaticMessageSource 为编码式资源注册提供了支持,DelegatingMessageSource 则可以看做是 MessageSource 的一个代理,必要时对 MessageSource 进行封装。

下面我们演示一下 MessageSource 的简单使用,首先我们定义好国际化资源 resource.properties:

resource.properties

spring=Spring framework is a good design, the latest version is {0}

resource_zh.properties

spring=Spring 框架設計精良,當前最新版本是 {0}

resource_zh_CN.properties

spring=Spring 框架设计精良,当前最新版本是 {0}

需要注意的是,如果资源文件包含了非 ASCII 字符,则需要将文本内容转换成 Unicode 编码,jdk 自带的 native2ascii 工具可以达到目的,操作如下:

native2ascii -encoding utf-8 resource_zh.properties resource_zh_tmp.properties

然后我们在配置文件中进行如下配置:

<!--推荐以 messageResource 作为 id-->
<beanid="messageResource"class="org.springframework.context.support.ResourceBundleMessageSource">
    <propertyname="basenames">
        <list>
            <value>i18n/resource</value>
        </list>
    </property>
</bean>

调用方式如下:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-core.xml");
Object[] params = {"4.3.8.RELEASE"};
System.out.println(context.getMessage("spring", params, Locale.ENGLISH));
System.out.println(context.getMessage("spring", params, Locale.TRADITIONAL_CHINESE));
System.out.println(context.getMessage("spring", params, Locale.SIMPLIFIED_CHINESE));

因为 ApplicationContext 同样实现了 MessageSource 接口,所以可以直接调用,但是这样调用的前提是配置中的 id 必须设置为 messageResource。输出如下:

Spring framework is a good design, the latest version is 4.3.8.RELEASE
Spring 框架設計精良,當前最新版本是 4.3.8.RELEASE
Spring 框架设计精良,当前最新版本是 4.3.8.RELEASE

7.2 MessageSource 的初始化过程

protected void initMessageSource(){
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {

        /*如果存在名称为 messageSource 的 bean*/

        // 初始化资源
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // 构造层次关系
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                hms.setParentMessageSource(this.getInternalParentMessageSource());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageSource [" + this.messageSource + "]");
        }
    } else {

        /*不存在名称为 messageSource 的 bean*/

        // 创建一个 DelegatingMessageSource 对象
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(this.getInternalParentMessageSource());
        this.messageSource = dms;
        // 以 messageSource 进行注册
        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 + "]");
        }
    }
}

前面我们在配置时推荐将 id 配置为 messageSource 是有原因的,通过阅读源码则一目了然,代码中硬编码要求我们的配置 messageSource 作为 bean 的名称,否则不执行初始化,而是创建一个默认的代理,如果我们利用 ApplicationContext 对象去获取对应的资源则会出现异常,否则我们就需要手动指定 getBean 时候的名称,但是这样做是不推荐的,既然框架以约定的方式提供了相应的实现,还是推荐以 messageSource 作为 id 进行配置。

8. 初始化事件广播器

事件广播和监听机制是典型的观察者模式的实现,而 ApplicationEventMulticaster 也是观察者模式中主题角色的典型实现。在 Spring 中,如果我们希望监听事件广播器广播的事件,则需要定义一个实现了 ApplicationListener 接口的监听器,Spring 支持监听器的编码注册和自动扫描注册,这个我们在后面小节中细说,我们先来看一下这里广播器的初始化过程:

protected void initApplicationEventMulticaster(){
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {

        /*包含名称为 applicationEventMulticaster 的 bean*/

        this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    } else {

        /*不包含名称为 applicationEventMulticaster 的 bean*/

        // 创建并注册一个 SimpleApplicationEventMulticaster
        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,进入该广播器的实现我们会发现如下逻辑:

public void multicastEvent(finalApplicationEvent event, ResolvableType eventType){
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : this.getApplicationListeners(event, type)) {
        Executor executor = this.getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                @Override
                public void run(){
                    invokeListener(listener, event);
                }
            });
        } else {
            // 回调各个监听器
            this.invokeListener(listener, event);
        }
    }
}
protected void invokeListener(ApplicationListener listener, ApplicationEvent event){
    ErrorHandler errorHandler = this.getErrorHandler();
    if (errorHandler != null) {
        try {
            // 回调监听的监听方法 onApplicationEvent
            listener.onApplicationEvent(event);
        } catch (Throwable err) {
            errorHandler.handleError(err);
        }
    } else {
        try {
            // 回调监听的监听方法 onApplicationEvent
            listener.onApplicationEvent(event);
        } catch (ClassCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || msg.startsWith(event.getClass().getName())) {
                // Possibly a lambda-defined listener which we could not resolve the generic event type for
                Log logger = LogFactory.getLog(getClass());
                if (logger.isDebugEnabled()) {
                    logger.debug("Non-matching event type for listener: " + listener, ex);
                }
            } else {
                throw ex;
            }
        }
    }
}

典型的回调观察者监听方法的逻辑,如果对于观察者模式了解的话,这里的逻辑会比较好理解。

9. 注册事件监听器

既然有被观察者,就应该有观察者,事件监听器就是我们的观察者,我们需要将其注册来监听事件消息,针对事件监听器的注册,我们可以以编码的方式进行注册,如果我们将其配置到配置文件中,容器也会自动扫描进行注册:

protected void registerListeners(){
    // 1.注册所有的编码添加的事件监听器
    for (ApplicationListener<?> listener : this.getApplicationListeners()) {
        this.getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 2. 扫描注册以配置方式添加的事件监听器(延迟加载)
    String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 3. 发布需要提前广播的事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            // 通知事件
            this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

10. 实例化所有非延迟加载的单例

记得最开始学习 Spring 框架的时候,就看到说 BeanFactory 和 ApplicationContext 有一个很大的区别就是 BeanFactory 在初始化容器时不会实例化 bean,而 ApplicationContext 则会实例化所有非延迟加载的单例 bean,而这个加载过程就在这里发生。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
    // 如果存在类型转换器,则进行加载
    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));
    }

    // 如果不存在 embedded value resolver 则设置一个默认的
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            publicStringresolveStringValue(String strVal){
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }

    // AOP支持,实例化 LoadTimeWeaverAware
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        this.getBean(weaverAwareName);
    }

    beanFactory.setTempClassLoader(null);

    // 冻结所有 bean 的定义,不再允许更改
    beanFactory.freezeConfiguration();

    // 实例化所有的非延迟加载的bean(非abstract && 单例 && 非延迟加载)
    beanFactory.preInstantiateSingletons();
}

由上述逻辑可以看到在执行实例化操作之前,容器会先校验一些必要的工具实例,如果之前没有注册则会创建一个默认的代替,然后会冻结所有的 bean 定义,毕竟即将开始实例化,后续的更改也不会再生效。在一些准备工作完毕之后,容器即开始实例化所有满足条件(非abstract && 单例 && 非延迟加载)的 bean。

Spring 4.1 增加了 SmartInitializingSingleton,实现了该接口的单例可以感知所有单例实例化完成的事件,而接口中声明的方法 afterSingletonsInstantiated 也在这里被回调:

public void preInstantiateSingletons()throwsBeansException{
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Pre-instantiating singletons in " + this);
    }

    // 遍历实例化满足条件的 bean
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
        RootBeanDefinition bd = this.getMergedLocalBeanDefinition(beanName);
        // 不是abstract && 单例 && 不是延迟加载的
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (this.isFactoryBean(beanName)) {
                // 工厂bean
                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
                        publicBooleanrun(){
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                } else {
                    isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    this.getBean(beanName);
                }
            } else {
                // 普通单例
                this.getBean(beanName);
            }
        }
    }

    // 4.1版本新特性 SmartInitializingSingleton
    for (String beanName : beanNames) {
        Object singletonInstance = this.getSingleton(beanName);
        // SmartInitializingSingleton 类型
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    publicObjectrun(){
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            } else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

11. 完成刷新过程,发布应用事件

Spring 很早就提供了 Lifecycle 接口,实现了该接口的 bean 可以感知到容器的启动和关闭状态,对应着接口的 start 和 stop 方法,而 start 方法的回调则位于这个时候发生:

protected void finishRefresh(){
    // 初始化 LifecycleProcessor
    this.initLifecycleProcessor();

    // 调用所有实现了 Lifecycle 的 start 方法
    this.getLifecycleProcessor().onRefresh();

    // 发布上下文刷新完毕事件
    this.publishEvent(new ContextRefreshedEvent(this));

    // 注册到 LiveBeansView MBean
    LiveBeansView.registerApplicationContext(this);
}

Lifecycle 对应方法的执行需要依赖于 LifecycleProcessor,我们可以自定义 LifecycleProcessor,否则容器会创建一个默认的 DefaultLifecycleProcessor,然后基于定义的 LifecycleProcessor 来调用满足条件 bean 的 start 方法。在完成了这一操作之后,容器的初始化过程基本上完成,这个时候容器可以将容器刷新完毕事件通知到对应的监听器。

到这里,高级容器的初始化过程我们已经探究完了,不同于 BeanFactory 在该阶段仅仅是将静态配置转换成容器中对应的 BeanDefinition 实例,ApplicationContext 因为需要实例化所有非延迟加载的单例,所以此时大部分的 bean 已经以实例的形式存在,后续我们再 getBean 也仅仅是针对非单例 bean 才需要执行复杂的实例化操作,所以在高级容器中本篇文章所探究的过程基本可以概括容器的大部分工作。

针对 Spring IoC 相关源码的探究,到这里就结束了,鉴于作者水平有限,文章中不免有错误之处,欢迎大家的指正,后续针对 IoC 有新的认识和见解,我也会回来更正和完善本系列的文章。鉴于最近项目繁重,Spring 源码的阅读解析工作暂告一段落,下次回归时我们来继续探究 AOP 的源码解析。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

软件测试的艺术

软件测试的艺术

梅尔斯 / 机械工业出版社 / 2006年01月 / 22.0

《软件测试的艺术》(原书第2版)成功、有效地进行软件测试的实用策略和技术:    基本的测试原理和策略      验收测试    程序检查和走查         安装测试    代码检查            模块(单元)测试    错误列表            测试规划与控制    同行评分            独立测试机构    黑盒、白盒测试    ......一起来看看 《软件测试的艺术》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具