SpringBoot源码解读与原理分析(二十五)IOC容器的刷新(六)

本文详细解读了SpringBoot源码中IOC容器的刷新过程,重点介绍了LifecycleProcessor、BeanFactory后置处理器、以及初始化阶段的多个扩展点,如BeanFactoryPostProcessors和BeanPostProcessor的使用场景和功能。
摘要由CSDN通过智能技术生成


前面五节,详细梳理了IOC容器刷新的前面十一步(7.1-7.11)以及一个重要的后置处理器ConfigurationClassPostProcessor,详见:

SpringBoot源码解读与原理分析(二十)IOC容器的刷新(一)
SpringBoot源码解读与原理分析(二十一)IOC容器的刷新(二)
SpringBoot源码解读与原理分析(二十二)IOC容器的刷新(三)ConfigurationClassPostProcessor
SpringBoot源码解读与原理分析(二十三)IOC容器的刷新(四)
SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五)

这一节继续梳理第十二步和第十三步(7.12-7.13),并总结一下IOC容器刷新过程中涉及的扩展点。

代码清单1AbstractApplicationContext.java

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

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

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

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

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

            // Register bean processors that intercept bean creation.
            // 7.6 初始化Bean的后置处理器
            registerBeanPostProcessors(beanFactory);

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

            // Initialize event multicaster for this context.
            // 7.8 初始化事件广播器
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 7.9 子类扩展的刷新动作
            onRefresh();

            // Check for listener beans and register them.
            // 7.10 注册监听器
            registerListeners();

            // 至此,BeanFactory创建完成

            // Instantiate all remaining (non-lazy-init) singletons.
            // 7.11 初始化所有剩下的单实例bean对象
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            // 7.12 刷新后的动作
            finishRefresh();
        } // catch ...
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            // 7.13 清理缓存
            resetCommonCaches();
        }
    }
}

7.12 完成容器的创建工作

// 7.12 刷新后的动作
finishRefresh();
代码清单2AbstractApplicationContext.java

protected void finishRefresh() {
    // 清除上下文级的资源缓存(例如扫描的ASM言数据)
    clearResourceCaches();
    // 初始化生命周期处理器
    initLifecycleProcessor();
    // 回调LifecycleProcessor的刷新动作
    getLifecycleProcessor().onRefresh();
    // 发布容器刷新完成的事件,触发特定监听器
    publishEvent(new ContextRefreshedEvent(this));
    LiveBeansView.registerApplicationContext(this);
}

7.12.1 LifecycleProcessor

SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五) 7.11.3.2 doCreateBean 5.bean对象的初始化 中提到,在initializeBean方法中会执行init-method、@PostConstruct等扩展点。

这一步的finishRefresh方法通过Lifecycle接口为bean对象提供了新的生命周期回调切入时机,可以在IOC容器的启动、停止时自动触发Lifecycle接口中的start方法和stop方法。

代码清单3AbstractApplicationContext.java

protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        // logger ...
    } else {
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        // logger ...
    }
}

由 代码清单3 可知,默认的LifecycleProcessor实现类是DefaultLifecycleProcessor。

7.12.2 getLifecycleProcessor().onRefresh()

代码清单4DefaultLifecycleProcessor.java

@Override
public void onRefresh() {
    startBeans(true);
    this.running = true;
}

private void startBeans(boolean autoStartupOnly) {
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    Map<Integer, DefaultLifecycleProcessor.LifecycleGroup> phases = new HashMap<>();
    lifecycleBeans.forEach((beanName, bean) -> {
        // 由于autoStartupOnly=true,所以这一段不会执行
        // 如果bean对象实现了SmartLifecycle接口且isAutoStartup方法的返回值为true,执行
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean);
            DefaultLifecycleProcessor.LifecycleGroup group = phases.get(phase);
            if (group == null) {
                group = new DefaultLifecycleProcessor.LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                phases.put(phase, group);
            }
            group.add(beanName, bean);
        }
    });
    // 由于上面代码没有执行,phases依旧为空,所以不会执行start方法
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<>(phases.keySet());
        Collections.sort(keys);
        for (Integer key : keys) {
            phases.get(key).start();
        }
    }
}

由 代码清单4 可知,由于startBeans(true)方法的参数为true,所以lifecycleBeans.forEach不会执行,phases始终为空,不会回调Lifecycle接口的start方法。

如果要回调Lifecycle接口的start方法,需要显式调用ApplicationContext的start方法。由于SpringBoot启动过程中没有回调start方法,所以仅实现Lifecycle接口的bean对象不会被回调。

如果需要在IOC容器刷新阶段自动回调start方法,bean对象需要实现SmartLifecycle接口且isAutoStartup方法的返回值为true(默认返回true)。

7.13 清除缓存

// 7.13 清理缓存
resetCommonCaches();
代码清单5AbstractApplicationContext.java

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

由 代码清单5 可知,IOC容器刷新的最后一步会清楚整个IOC容器刷新期间的缓存。

至此,IOC容器的刷新全部完成。

7.14 IOC容器初始化中的扩展点

在IOC容器的初始化逻辑中由许多的扩展点可供开发者切入利用。

7.14.1 invokeBeanFactoryPostProcessors

refresh方法中,第一个可切入的扩展点是第五步的invokeBeanFactoryPostProcessors方法,即BeanFactory创建后的后置处理器的执行。

7.14.1.1 ImportSelector和ImportBeanDefinitionRegistrar

第一个扩展点是ImportSelector和ImportBeanDefinitionRegistrar接口

SpringBoot源码解读与原理分析(二十二)IOC容器的刷新(三)ConfigurationClassPostProcessor 7.5.7.3 ConfigurationClassParser的parse方法 中提到,ConfigurationClassPostProcessor的执行过程中会解析@Import注解,提取出其中的ImportBeanDefinitionRegistrar并执行。

ImportSelector在该阶段只能获取当前@Import标注的注解配置类的信息,而ImportBeanDefinitionRegistrar在该阶段除了能获取当前@Import标注的注解配置类的信息,还能获取BeanDefinitionRegistrar,由此可见可供扩展的动作主要是给BeanDefinitionRegistrar中编程式注册新的BeanDefinition

7.14.1.2 BeanDefinitionRegistryPostProcessor

第二个扩展点是BeanDefinitionRegistryPostProcessor。它可以获取BeanDefinitionRegistry对象,利用该对象可以直接向IOC容器编程式注册新的BeanDefinition,以及移除容器中已有的BeanDefinition。

一般情况下,自定义的BeanDefinitionRegistryPostProcessor的执行时机比内置的ConfigurationClassPostProcessor要晚,因为ConfigurationClassPostProcessor实现了PriorityOrdered接口,这个接口的优先级最高。

特殊情况下,要使自定义的BeanDefinitionRegistryPostProcessor的执行时机比内置的ConfigurationClassPostProcessor更早,可以让自定义的BeanDefinitionRegistryPostProcessor也实现PriorityOrdered接口,则能达到目的。

7.14.1.3 BeanFactoryPostProcessor

第三个扩展点是BeanFactoryPostProcessor。它可以获取ConfigurableListableBeanFactory对象,可以获取和修改现有的BeanDefinition(原则上不能注册新的BeanDefinition)。

另外,BeanFactoryPostProcessor的处理阶段中允许提早初始化bean对象,但是这个阶段只有ApplicationContextAwareProcessor注册到了BeanFactory中,没有其余关键的BeanFactoryPostProcessor,因此这个阶段初始化的bean对象有一个共同的特点,可是使用Aware回调注入,但无法使用@Autowired等依赖注入的注解,且不会产生任何代理对象

7.14.2 finishBeanFactoryInitialization

refresh方法中,第二个可切入的扩展点是第十一步的finishBeanFactoryInitialization方法,即初始化非延迟加载的单实例bean对象。

7.14.2.1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

MergedBeanDefinitionPostProcessor的postProcessBeforeInstantiation方法使用在createBean方法中的resolveBeforeInstantiation方法中。

在bean对象实例化之前,InstantiationAwareBeanPostProcessor可以前置拦截bean对象的实例化动作,来代替真正的bean对象实例化逻辑。如果成功实例化了bean对象,则直接返回,否则执行真正的bean对象实例化流程。

7.14.2.2 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors

SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法使用在doCreateBean方法中的createBeanInstance方法中。

如果实例化之前InstantiationAwareBeanPostProcessor没有拦截成功,则会执行真正的bean对象实例化逻辑,通过构造方法实例化对象。如果一个bean对象的所属类型中定义了多个构造方法,那么选择哪一个构造方法,就是其中一个扩展点。

底层在筛选构造方法是,会获取所有SmartInstantiationAwareBeanPostProcessor,回调其determineCandidateConstructors方法获取可选择的构造方法。

一般情况下,SmartInstantiationAwareBeanPostProcessor在SpringFramework内部未内置使用逻辑,了解即可。

7.14.2.3 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法使用在doCreateBean方法中的applyMergedBeanDefinitionPostProcessors方法中。

由于已经执行了doCreateBean方法中的createBeanInstance方法,此时bean对象已经实例化,但没有进行属性赋值和依赖注入。紧接着会回调所有的MergedBeanDefinitionPostProcessor,收集bean对象所属Class中的注解信息

SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五) 7.11.3.2 doCreateBean 2.属性赋值前的注解信息收集 中已经列出了3个关键的MergedBeanDefinitionPostProcessor,分别是InitDestroyAnnotationBeanPostProcessor(收集@PostConstruct注解和@PostDestroy注解)、CommonAnnotationBeanPostProcessor(收集JSR-250规范中的注解,如@WebServiceRef、@EJB、 @Resource等)、AutowiredAnnotationBeanPostProcessor(收集@Autowired、@Value、@Inject注解)。

7.14.2.4 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

InstantiationAwareBeanPostProcessor的使用在doCreateBean方法中的populateBean方法中。

这个扩展点根据InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法的返回值决定是否继续执行后续的populateBean方法和initializeBean方法初始化对象,起到流程控制的作用。

7.14.2.5 InstantiationAwareBeanPostProcessor#postProcessProperties

InstantiationAwareBeanPostProcessor的postProcessProperties方法的使用是在doCreateBean方法中的populateBean方法中。

这个扩展点会将bean对象对应的PropertyValues中封装赋值和注入的属性和依赖对象实际应用到bean对象的实例中。

通常情况下,这一阶段起作用的后置处理器是AutowiredAnnotationBeanPostProcessor,它会收集bean对象所属的Class类型中标注了@Autowired、@Value等注解的属性和方法,并反射赋值/调用。

7.14.2.6 BeanPostProcessor

BeanPostProcessor的postProcessProperties方法的使用是在doCreateBean方法中的initializeBean方法中。

属性赋值和依赖注入完成后,下一个核心步骤是initializeBean方法,该方法包含BeanPostProcessor的前后两个执行动作postProcessBeforeInitializationpostProcessAfterInitialization给已经完成属性赋值和依赖注入的bean对象添加一些额外的属性的赋值、回调以及生成代理对象等动作

7.12.2.7 SmartInitializingSingleton

SmartInitializingSingleton的使用是在preInstantiateSingletons方法中。

在所有非延迟加载的单实例bean对象全部初始化完成后,最后一个扩展点是SmartInitializingSingleton。它会提取出所有实现了SmartInitializingSingleton接口的bean对象,回调其afterSingletonsInstantiated方法,这使得BeanFactory也有机会参与bean对象初始化完成后的扩展处理

本节完,更多内容请查阅分类专栏:SpringBoot源码解读与原理分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰色孤星A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值