Spring源码分析-Spring启动和Bean的加载过程

Spring的初始化,就是SpringContext的初始化。

SpringContext的初始化就是启动Spring项目时要做的第一件事。

我们测试Context初始化可以自己创建Context:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("org.springframework.context.annotation6");//自己的包路径
context.refresh();

初始化上下文最重要的就是refresh方法,这里的AnnotationConfigApplicationContext的父类是:AbstractApplicationContext。

AbstractApplicationContext它也是所有*ApplicationContext的父类。

那么我们来看看refresh方法都做了什么:

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 1.刷新前准备工作,包括设置启动时间,是否激活标识位,初始化属性源(property source)配置
            prepareRefresh();

            // 2.创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            /**
             * 3.准备创建好的beanFactory(给beanFactory设置ClassLoader,设置SpEL表达式解析器,设置类型转化器【能将xml String类型转成相应对象】,
             * 增加内置ApplicationContextAwareProcessor对象,忽略各种Aware对象,注册各种内置的对账对象【BeanFactory,ApplicationContext】等,
             * 注册AOP相关的一些东西,注册环境相关的一些bean
             */
            prepareBeanFactory(beanFactory);

            try {
                // 4.模板方法,为容器某些子类扩展功能所用(工厂后处理器)这里可以参考BeanFactoryPostProcessor接口的postProcessBeanFactory方法
                postProcessBeanFactory(beanFactory);

                // 5.调用所有BeanFactoryPostProcessor注册为Bean
                invokeBeanFactoryPostProcessors(beanFactory);

                // 6.注册所有实现了BeanPostProcessor接口的Bean
                registerBeanPostProcessors(beanFactory);

                // 7.初始化MessageSource,和国际化相关
                initMessageSource();

                // 8.初始化容器事件传播器
                initApplicationEventMulticaster();

                // 9.调用容器子类某些特殊Bean的初始化,模板方法
                onRefresh();

                // 10.为事件传播器注册监听器
                registerListeners();

                // 11.初始化所有剩余的bean(普通bean)
                finishBeanFactoryInitialization(beanFactory);

                // 12.初始化容器的生命周期事件处理器,并发布容器的生命周期事件
                finishRefresh();
            } catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // 销毁已创建的bean
                destroyBeans();
                // 重置`active`标志
                cancelRefresh(ex);
                throw ex;
            } finally {
                // 13.重置一些缓存
                resetCommonCaches();
            }
        }
    }

步骤1-4都是一些准备工作

5、6步是初始化BeanPostProcessor的实现类(如果有的话)。那么这个BeanPostProcessor接口是干什么的呢,看代码:

public interface BeanPostProcessor {
    // 注意这个方法名称关键的是before这个单词
    Object postProcessBeforeInitialization(Object bean, String beanName) 
        throws BeansException;

    // 注意这个方法名称关键的是after这个单词
    Object postProcessAfterInitialization(Object bean, String beanName) 
        throws BeansException;
}

看到这个接口中只有两个方法,简单说就是:初始化之前做的事、初始化之后做的事。初始化什么呢,Bean。

关于BeanPostProcessor这篇文章讲的更详细:https://www.cnblogs.com/tuyang1129/p/12866484.html

这篇文章中还举了一个例子,自己创建两个bean,和一个PostProcessorBean,发现在初始化非BeanPostProcessor的时候,都会触发PostProcessorBean的Before和After方法。

这个就像是切面,可以在Bean创建之前和之后做一些事情,而被初始化的Bean是无感知的。

7-10我们后续补全(TODO)

第11步,就是我们期待已久的Bean初始化了。

我们看一下调用链:

finishBeanFactoryInitialization() --> DefaultListableBeanFactory.preInstantiateSingletons() --> 循环beanDefinitionNames中的所有bean定义,每个调用getBean进行初始化 --> AbstractBeanFactory.getBean() --> AbstractbeanFactory.doGetBean()

这里的AbstractBeanFactory.doGetBean就是Bean初始化的核心方法。

这个方法的逻辑是: 先从singletonObjects或earlySingletonObjects这两个Map中取,如果都没有,说明还没有初始化。那么就初始化,然后放入earlySingletonObjects中。

 

posted @ 2022-01-30 18:08  hucat  阅读(111)  评论(0)    收藏  举报