Spring IOC原理-IOC容器的生命周期概述

从 0 开始深入学习 Spring 专栏目录总览

前面我们拿出 5 章的篇幅,研究了 Bean 的完整生命周期,在此期间我们也对整个 IOC 容器的生命周期了解了部分流程。本章咱来完整的看一下 IOC 容器的一个刷新动作中,会有哪些动作的触发,以及从这些流程中,我们能梳理出哪些可以切入进 SpringFramework 内部流程的扩展点。

本章主要涉及的原理部分:

  • ApplicationContext#refresh 方法整体概述
  • refresh 方法中可以切入的扩展点

好了我们开始,前面我们已经反复多次提到 ApplicationContext 的 refresh 方法是整个 IOC 容器初始化的核心,它一共分为 13 步:

1. AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        // 1. 初始化前的预处理
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 2. 获取BeanFactory,加载所有bean的定义信息(未实例化)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // 3. BeanFactory的预处理配置
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            // 4. 准备BeanFactory完成后进行的后置处理
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            // 5. 执行BeanFactory创建后的后置处理器
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            // 6. 注册Bean的后置处理器
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            // 7. 初始化MessageSource
            initMessageSource();

            // Initialize event multicaster for this context.
            // 8. 初始化事件派发器
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 9. 子类的多态onRefresh
            onRefresh();

            // Check for listener beans and register them.
            // 10. 注册监听器
            registerListeners();
          
            //到此为止,BeanFactory已创建完成

            // Instantiate all remaining (non-lazy-init) singletons.
            // 11. 初始化所有剩下的单例Bean
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            // 12. 完成容器的创建工作
            finishRefresh();
        } // catch ......

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            // 13. 清除缓存
            resetCommonCaches();
        }
    }
}

本章我们重点研究的,是这里面每一步都做了哪些事情,对于里面涉及的细节不作过多研究,感兴趣的小伙伴可以移步 boot 小册第 11 – 15 章

考虑到部分方法的实现中涉及到的源码和注释会很多,会很影响阅读体验,小册只会截取关键步骤的关键源码进行解读。

1.1 prepareRefresh – 初始化前的预处理

protected void prepareRefresh() {
    // 此处会记录启动时间,切换IOC容器的状态
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    // logger ......

    // 初始化属性配置
    initPropertySources();

    // 属性校验
    getEnvironment().validateRequiredProperties();

    // 省略源码 - 初始化早期事件
}

这一步中,大多数的动作都是前置性的准备,而且基本上这些准备的动作在我们现阶段学习的内容中几乎都用不到,小伙伴们可以暂且忽略即可。

initPropertySources 方法在基于 web 环境的 ApplicationContext 子类中有重写,在 boot 小册的第 11 章中有提及到,感兴趣的小伙伴们可以先去看一看。

关于早期事件的概念,可能现阶段解释起来比较复杂,后续再考虑补充。

1.2 obtainFreshBeanFactory – 初始化BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

这个方法我们在第 33 章有研究过了,基于 xml 配置文件的 ApplicationContext 中,在该步骤会解析 xml 配置文件,封装 BeanDefinition 。但是,基于注解配置类的 ApplicationContext 就不太一样了,上一章中我们看到,GenericApplicationContext 的 refreshBeanFactory 方法中,有一个 CAS 判断的动作,它控制着 GenericApplicationContext 不能反复刷新。所以从这一步我们能知道的,是基于 xml 配置文件的 ApplicationContext 可以反复刷新,基于注解配置类的 ApplicationContext 只能刷新一次

1.3 prepareBeanFactory – BeanFactory的预处理动作

这个方法比较长,但仔细观察可以发现源码是非常有条理的:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 给BeanFactory中设置类加载器、表达式解析器
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 1.3.1 编码注册ApplicationContextAwareProcessor
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 1.3.2 以下几个Aware接口的回调注入不由BeanFactory负责
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 1.3.3 以下几个类型的自动注入会直接绑定
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 又编码注册监听器钩子
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 又是Load Time Weaver相关的部分,AOP再解释
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认的运行时环境Environment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

这部分很好理解吧!不过这个方法内信息量有点大,我们有必要研究一下。

1.3.1 ApplicationContextAwareProcessor的注册

可以发现,前面在第 35 章 1.4.2.2 节提到的 Aware 接口注入的后置处理器中,那个起核心作用的 ApplicationContextAwareProcessor 是在此处注册的,而且它负责注入的 6 个 Aware 接口,恰好就是上面源码中忽略的 6 个接口,也证实了 ApplicationContextAwareProcessor 接管 BeanFactory 自动注入这一设计。

如何理解这一设计:BeanFactory 来自 spring-beans 包,而 ApplicationContext 来自 spring-context 包。由于 context 依赖 beans ,而 beans 本身可以单独存在。在没有 context 包的环境下,BeanFactory 本身也可以作为一个普通的 IOC 容器来处理依赖查找和自动类型注入,而引入 context 包后,出现了更多的内部组件,注入的要求也就更复杂。本着单一职责职责分离的原则,BeanFactory 还是干原来的事情,扩展的 Aware 回调注入则交给 context 包中的 ApplicationContextAwareProcessor 搞定。

1.3.2 ignoreDependencyInterface的设计

既然有 6 个 Aware 回调接口的工作被 ApplicationContextAwareProcessor 接管了,那 BeanFactory 本身就不再需要考虑这 6 个接口的注入了。这 6 个接口最终会存储到 AbstractAutowireCapableBeanFactory 的 ignoredDependencyInterfaces 变量中:

private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();

而它被利用的时机,是在 bean 生命周期中的属性赋值 populateBean 阶段:

    // ......
    if (needsDepCheck) {
        if (filteredPds == null) {
            // 此处ignoreDependencyInterface会被利用
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        // 将PropertyValues应用给bean
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

这个源码片段是不是很熟悉呀,在第 35 章中,我们讲解 applyPropertyValues 方法,就是截取了这一小段,而上面露头的 filterPropertyDescriptorsForDependencyCheck 方法,内部就使用了 ignoredDependencyInterfaces 这个集合检查那些依赖的 Aware 接口。

这里多说一嘴 Aware 接口在没有被 BeanFactory 忽略掉的执行原则吧。通常来讲,Aware 接口都会定义一个 setXXX 的方法(如 BeanFactoryAware 接口的 setBeanFactory 方法),同时实现了 Aware 接口的方法通常都会在成员属性中定义一个与回调注入类型相同的属性变量(如实现了 BeanFactoryAware 接口的类,通常都会定义一个 private BeanFactory beanFactory; )。如果是按照这种设计编写的代码,BeanFactory 会认定这个属性可以受自动注入的支持( autowire-mode ),并对这个属性进行依赖注入。简单的讲,BeanFactory 可以支持的自动注入的属性必须带有 setter 方法,而 Aware 接口的方法定义风格刚好是 setter 的风格,所以只需要求实现了 Aware 接口的类,定义属性时,属性名与 setter 方法对应的名称一致即可( setPerson → person )。

1.3.3 registerResolvableDependency的设计

这个 registerResolvableDependency 方法,可能小伙伴们看了源码之后会更容易理解:

// Map from dependency type to corresponding autowired value.
// 从依赖属性的类型映射到相应的自动装配值
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
    Assert.notNull(dependencyType, "Dependency type must not be null");
    if (autowiredValue != null) {
        // check throw ex ......
        this.resolvableDependencies.put(dependencyType, autowiredValue);
    }
}

是不是一下子就看明白了,调用这个方法后,在 BeanFactory 再遇到特定类型的属性注入时,会直接从这个 resolvableDependencies 的 Map 中找出对应的值,直接注入进去(相当于预先指定好了哪个类型注入哪个值,不需要额外考虑)。

1.4 postProcessBeanFactory – BeanFactory的后置处理

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

这个方法在 AbstractApplicationContext 中是一个模板方法,它的重写在基于 web 环境的 ApplicationContext 子类中有实现,回头我们学到 WebMvc 章节中再来看它。

1.5 invokeBeanFactoryPostProcessors – 执行BeanFactoryPostProcessor

这个方法我们前面已经看过了,它会执行所有的 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor ,主要工作是包扫描、解析配置类等,不再赘述。

1.6 registerBeanPostProcessors – 初始化BeanPostProcessor

这个方法我们前面也看过了,它会把所有的 BeanPostProcessor 都注册到位,这里面的处理逻辑与上面的 invokeBeanFactoryPostProcessors 类似,忘记的小伙伴们记得看前面第 34 章哦。

1.7 initMessageSource – 初始化国际化组件

这个方法的源码小册不在此处贴出,它涉及到国际化的知识。早在第 15 章我们就说过,国际化的内容小册会放到 WebMvc 章节中讲解,so 此处先留下一个坑,回头到了 WebMvc 中再填。

1.8 initApplicationEventMulticaster – 初始化事件广播器

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);
        // logger ......
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        // logger ......
    }
}

这部分的内容非常简单了,它会构造一个 SimpleApplicationEventMulticaster ,并注册进 BeanFactory 中,仅此而已。

1.9 onRefresh – 子类扩展的刷新动作

protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}

该部分又是一个模板方法,而它的扩展在纯 Spring 环境下是找不到的,不过在 SpringBoot 中,有子类对这个方法的重写,感兴趣的小伙伴可以移步 boot 小册第 16 章学习。

1.10 registerListeners – 注册监听器

protected void registerListeners() {
    // 注册所有已经被创建出来的ApplicationListener,绑定到ApplicationEventMulticaster中
    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!
    // 此处不会实例化ApplicationListener,而是只绑定name
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 广播早期事件(后续再解释)
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

这个方法共分为三个小段,条理也非常清晰。不过要注意一点,此处那些没有初始化的 ApplicationListener 并没有被实例化,而是会等到下一步 finishBeanFactoryInitialization 方法中才会被创建出来(注释中也说了,不要在此处创建,因为框架希望让那些后置处理器去干预它们)。

1.11 finishBeanFactoryInitialization – 初始化剩余的单实例bean

这个方法就是一个一个的循环初始化那些非延迟加载的单实例 bean 了,整个流程我们已经在第 34 、35 章讲过了,这里不再赘述。

1.12 finishRefresh – 刷新后的动作

protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    // 清除上下文级别的资源缓存
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    // 为当前ApplicationContext初始化一个生命周期处理器
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    // 将refresh的动作传播到生命周期处理器
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    // 广播事件
    publishEvent(new ContextRefreshedEvent(this));

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

这个方法小册在第 35 章也讲到过了,它主要是初始化 LifecycleProcessor 、广播刷新完成的事件,整体也没什么难的。

1.13 resetCommonCaches – 清除缓存

protected void resetCommonCaches() {
    ReflectionUtils.clearCache();
    AnnotationUtils.clearCache();
    ResolvableType.clearCache();
    CachedIntrospectionResults.clearClassLoader(getClassLoader());
}

这就没啥好说的了吧,这些乱七八糟的缓存都可以干掉了(品种还不少呢),因为准备工作都完成了。

1.14 小结

纵观整个 refresh 方法,每个动作的职责都很清晰,而且非常的有条理性。这个过程中,有对 BeanFactory 的处理,有对 ApplicationContext 的处理,有处理 BeanPostProcessor 的逻辑,有准备 ApplicationListener 的逻辑,最后它会初始化那些非延迟加载的单实例 bean 。整个 refresh 方法走下来,ApplicationContext 也就全部初始化完毕了。

2. ApplicationContext初始化中的扩展点

看了上面的整个逻辑,想必小伙伴们也比较清楚的理解 ApplicationContext 中的初始化逻辑了。IOC 原理的最后一个部分,我们来梳理一下,整个 ApplicationContext 的初始化逻辑中,都有哪些扩展点可供我们切入利用。清楚地理解这些扩展点,可以让我们在后续扩展 Spring 时更加容易和游刃有余。

一般情况下,我们不会在 ApplicationContext 的初始化和 refresh 动作之间作太多的处理,主要还是从 refresh 方法本身出发考虑,故以下梳理的扩展点都来自于 refresh 方法开始触发时。

2.1 invokeBeanFactoryPostProcessors

前四个方法中,在普通的 ApplicationContext 下都无法切入,所以只能在第 5 步 invokeBeanFactoryPostProcessors 方法中切入了。而这个方法中可供切入的点实在是太多了,咱一一来数。

2.1.1 ImportSelector&ImportBeanDefinitionRegistrar

咦,没想到吧,第一个竟然不是 BeanFactoryPostProcessor 或者BeanDefinitionRegistryPostProcessor ,原因是它们的执行时机通常都在 ConfigurationClassPostProcessor 之后啦,而 ConfigurationClassPostProcessor 的执行过程中,会解析 @Import 注解,取出里面的 ImportBeanDefinitionRegistrar 并执行,所以第一个扩展点是 ImportSelector 和 ImportBeanDefinitionRegistrar 了。

ImportSelector 在该阶段只能拿到当前 @Import 标注的注解配置类的信息(如下面代码中 BarImportSelector 只能拿到 BarConfiguration 的信息)

@Import(BarImportSelector.class)
@Configuration
public class BarConfiguration { ... }

ImportBeanDefinitionRegistrar 在该阶段除了可以获取到当前 @Import 标注的注解配置类的信息之外,更重要的是能拿到 BeanDefinitionRegistry ,由此可供扩展的动作主要是给 BeanDefinitionRegistry 中注册新的 BeanDefinition 。

不过小伙伴如果把 BeanDefinitionRegistry 看做 DefaultListableBeanFactory 也不是不行,只是说考虑到依赖倒转的设计,此处还是拿接口比较合适。

2.1.2 BeanDefinitionRegistryPostProcessor

这个切入算是比较简单明了的吧,前面我们也已经学过了,使用 BeanDefinitionRegistryPostProcessor 可以拿到 BeanDefinitionRegistry 的 API ,直接向 IOC 容器中注册新的 BeanDefinition 。

不过这里面有一点要注意,刚才上面也提到了,一般情况下,自定义的 BeanDefinitionRegistryPostProcessor 执行时机比内置的 ConfigurationClassPostProcessor 要晚,这也是 SpringFramework 最开始的设计( ConfigurationClassPostProcessor 实现了 PriorityOrdered 接口,这个接口的优先级最高)。

注意上面的话说的是 “一般情况下” 哦,说明小册有留台阶的。如果小伙伴们非要让自己写的 BeanDefinitionRegistryPostProcessor 执行时机比 ConfigurationClassPostProcessor 早,可以让后置处理器实现 PriorityOrdered 接口,声明较高执行优先级(不能是 Ordered.LOWEST_PRECEDENCE ,否则排序规则会变成字母表顺序)。经过这样的设计之后,自定义的 BeanDefinitionRegistryPostProcessor 就可以在 ConfigurationClassPostProcessor 之前执行了。

2.1.3 BeanFactoryPostProcessor

BeanFactoryPostProcessor 的切入时机紧随 BeanDefinitionRegistryPostProcessor 之后,本来它没什么好说的了,小伙伴们只需要注意一下,在 BeanFactoryPostProcessor 的切入回调中,可以拿到的参数是 ConfigurableListableBeanFactory ,拿到它就意味着,我们在这个阶段按理来讲不应该再向 BeanFactory 中注册新的 BeanDefinition 了,只能获取和修改现有的 BeanDefinition 。

另外,还要注意一点,javadoc 中有说,BeanFactoryPostProcessor 的处理阶段是可以提早初始化 bean 对象的,因为这个阶段下只有 ApplicationContextAwareProcessor 注册到了 BeanFactory 中,没有其余关键的 BeanPostProcessor ,所以这个阶段初始化的 bean 有一个共同的特点:能使用 Aware 回调注入,但无法使用 @Autowired 等自动注入的注解进行依赖注入,且不会产生任何代理对象

2.2 registerBeanPostProcessors

所有 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 都处理完之后,下一步是初始化 BeanPostProcessor 。这个逻辑我们之前也都看过了,但这个阶段没有可以切入影响该阶段的时机,所以该阶段跳过。

2.3 finishBeanFactoryInitialization

一下子就来到最复杂的初始化 bean 的这一步了。这里面的切入时机才多呢,前面看 bean 的实例化和初始化过程中,有非常多可供切入的时机,我们逐个来看。

本方法中涉及到的所有切入点均为针对单个 bean 的扩展。

2.3.1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

从 bean 的创建阶段之前,就有 InstantiationAwareBeanPostProcessor 来拦截创建了,每个 bean 在创建之前都会尝试着使用 InstantiationAwareBeanPostProcessor 来代替创建,如果没有任何 InstantiationAwareBeanPostProcessor 可以拦截创建,则会走真正的 bean 对象实例化流程。

在 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法中,只能拿到 bean 对应的 Class 类型,以及 bean 的名称(当然啦,本来就是凭空造,有 Class 类型就够了),如果方法没有返回值,则代表 InstantiationAwareBeanPostProcessor 不参与拦截 bean 创建的动作。

2.3.2 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors

如果在实例化 bean 之前,InstantiationAwareBeanPostProcessor 没有起到作用,就会通过构造器创建对象。如果一个 bean 有多个构造器,如何选择合适的构造器去创建对象就是很重要的一步。在 34 章 2.4.4 节我们看到,筛选构造器的核心方法是 determineConstructorsFromBeanPostProcessors ,它会在底层寻找所有 SmartInstantiationAwareBeanPostProcessor ,回调 determineCandidateConstructors 方法获取可选择的构造器:

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
        throws BeansException {
    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                if (ctors != null) {
                    return ctors;
                }
            }
        }
    }
    return null;
}

在第 27 章中我们就说过这个 SmartInstantiationAwareBeanPostProcessor 的使用了,如果在这里打入 Debug 断点时,程序代码运行时可以停在断点,但不会有任何返回,这个现象的产因是:默认情况下 ConfigurationClassPostProcessor 会向 IOC 容器注册一个 ImportAwareBeanPostProcessor ,但它又没有重写 determineCandidateConstructors 方法,就造成了这个现象。

所以一般情况下,SmartInstantiationAwareBeanPostProcessor 在 SpringFramework 内部是用不到的,我们平时开发不是特殊场景也用不上,这个小伙伴们知道一下就可以了。

2.3.3 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

在 createBeanInstance 方法执行完毕之后,此时 bean 对象已经创建出来了,只是没有任何属性值的注入而已。此时 doCreateBean 方法会走到 applyMergedBeanDefinitionPostProcessors 方法,让这些 MergedBeanDefinitionPostProcessor 去收集 bean 所属的 Class 中的注解信息。在第 35 章中小册有列出三个关键的 MergedBeanDefinitionPostProcessor ,它们分别是 InitDestroyAnnotationBeanPostProcessor (收集 @PostConstruct 与 @PreDestroy 注解)、CommonAnnotationBeanPostProcessor (收集 JSR 250 的其它注解)、AutowiredAnnotationBeanPostProcessor (收集自动注入相关的注解)。

在此处切入扩展,意味着可以对 bean 对象所属的 Class 作一些处理或者收集的动作(当然也可以进行属性赋值等动作,但考虑到职责分离,该步骤还是不要瞎搞为好 ~ ~)。

2.3.4 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

等这些 MergedBeanDefinitionPostProcessor 都工作完毕后,此时 bean 对象所属的 Class 中的信息都收集完毕了,接下来还得让 InstantiationAwareBeanPostProcessor 出场,它要负责控制是否继续走接下来的 populateBean 和 initializeBean 方法初始化 bean 。

所以如果在这里切入扩展的话,只能做到流程控制的作用。

2.3.5 InstantiationAwareBeanPostProcessor#postProcessProperties

又又又又又是它!不过这次它调用的是 postProcessProperties 方法,这个步骤会将 bean 对象对应的 PropertyValues 中封装赋值和注入的数据应用给 bean 实例。通常情况下,在该阶段 SpringFramework 内部起作用的后置处理器是 AutowiredAnnotationBeanPostProcessor ,它会搜集 bean 所属的 Class 中标注了 @Autowired 、@Value 、@Resource 等注解的属性和方法,并反射赋值 / 调用。

在此处扩展逻辑的话,相当于扩展了后置处理器的属性赋值 + 依赖注入的自定义逻辑。当这个动作执行完毕之后,就不会再有属性赋值和组件注入的回调了。

2.3.6 BeanPostProcessor

接下来的两个动作就发生在 initializeBean 方法中了,它就是 BeanPostProcessor 的前后两个执行动作 postProcessBeforeInitialization 和 postProcessAfterInitialization 。进入到 initializeBean 方法后,bean 的生命周期已经到了初始化逻辑回调的阶段,此时 bean 中应该注入的属性均已完备,BeanPostProcessor 的切入也只是给 bean 添加一些额外的属性的赋值、回调等等,以及生成代理对象。

所以,在此处切入扩展逻辑,相当于针对一个接近完善的 bean 去扩展 / 包装。当后置处理器执行完 postProcessAfterInitialization 方法后,基本上就代表 bean 的初始化结束了。

2.3.7 SmartInitializingSingleton

这个扩展在第 35 章我们有说过,它来自 SpringFramework 4.1 ,它是在所有非延迟加载的单实例 bean 全部初始化完成后才回调的。这个阶段底层会取出所有实现了 SmartInitializingSingleton 接口的 bean ,去回调 afterSingletonsInstantiated 方法。而且当时小册还说了,这个设计只是为了让 BeanFactory 也能插一脚初始化的后处理,仅此而已。

这个扩展是针对单个 bean 的, 不是切入所有 bean 的,所以严格意义上讲它属于 bean 初始化的扩展点。不过话又说回来,它是在 BeanFactory 把单实例 bean 都初始化完成后统一回调的,又属于一个整体动作,所以小册也就把它拿出来了。

免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » Spring IOC原理-IOC容器的生命周期概述