Spring源码之Spring容器启动流程

1. 前言

        Spring提供了XML配置和Java配置两种配置方式,分别对应ClassPathXmlApplicationContext和AnnotationConfigApplicationContext两个入口类,这两个入口类均继承了AbstractApplicationContext类。本文将通过Java配置+AnnotationConfigApplicationContext来分析Spring容器的启动流程。以下内容均基于Spring5.3.37版本进行分析。

2. 初始化流程

        我们可以通过如下方式来创建一个基于AnnotationConfigApplicationContext的Spring容器:

// 实例化
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册要处理的组件类
context.register(Config.class);
// 基于Java的配置进行配置的加载或刷新持久化
context.refresh();

对应流程图如下图所示:

接下来将基于上述流程,分析每个流程节点涉及的内容。

2.1 AnnotationConfigApplicationContext实例化

        AnnotationConfigApplicationContext的实例化三步,分别为:

1.设置BeanFactory

2.设置AnnotatedBeanDefinitionReader

3.设置ClassPathBeanDefinitionScanner

2.1.1 设置BeanFactory

        AnnotationConfigApplicationContext继承了GenericApplicationContext,因此在实例化AnnotationConfigApplicationContext之前,会先调用父类GenericApplicationContext的构造方法。GenericApplicationContext的构造方法里创建了一个DefaultListableBeanFactory对象,并设置给了当前ApplicationContext的beanFactory,用于后续Bean的创建。

2.1.2 设置AnnotatedBeanDefinitionReader

        构造了AnnotatedBeanDefinitionReader,并对BeanFactory进行设置和添加Post Process(后置处理器)。涉及的步骤如下代码所示:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    // 设置BeanDefinitionRegistry
    this.registry = registry;
    // 构建并设置ConditionEvaluator(用于计算条件注解的内部类)
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 在给定的BeanDefinitionRegistry注册所有注解相关的Post Process(后置处理器)
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

其中AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)涉及的详细内容如下:
1.设置dependencyComparator:AnnotationAwareOrderComparator。
AnnotationAwareOrderComparator是一个Comparator,通过获取实现了org.springframework.core.Ordered接口、有@Order注解、有@Priority注解的对象所定义的排序值进行排序。
2.设置autowireCandidateResolver:ContextAnnotationAutowireCandidateResolver。
ContextAnnotationAutowireCandidateResolver用来确定指定的Bean定义是否可以用于特定依赖项的autowire候选者。
3.向BeanFactory中添加ConfigurationClassPostProcessor的BeanDefinition。
ConfigurationClassPostProcessor是一个BeanFactoryPostProcessor的实现,用于有@Configuration注解的类的引导处理。
4.向BeanFactory中添加AutowiredAnnotationBeanPostProcessor的BeanDefinition。AutowiredAnnotationBeanPostProcessor是一个BeanFactoryPostProcessor的实现,用于自动注入带注解的字段、setter方法和任意构造方法,默认情况下,这些要注入的类成员是通过注解来发现的,默认是Spring的@Autowired和@Value注解。
5.检查是否支持JSR-250,若支持则向BeanFactory中添加CommonAnnotationBeanPostProcessor的BeanDefinition。
CommonAnnotationBeanPostProcessor是一个BeanFactoryPostProcessor的实现,支持开箱即用的常见Java注解,特别是javax中的JSR-250的相关注解。通过继承InitDestroyAnnotationBeanPostProcessor的预配置注解类型,支持了PostConstruct和PreDestroy注解,对应分别为init注解和destroy注解。
6.检查是否支持JPA,若支持则向BeanFactory中添加PersistenceAnnotationBeanPostProcessor的BeanDefinition。
7.向BeanFactory中添加EventListenerMethodProcessor的BeanDefinition。
EventListenerMethodProcessor是一个BeanFactoryPostProcessor的实现,用来对@EventListener提供支持。在afterSingletonsInstantiated方法中使用EventListenerFactory对标注了@EventListener的方法进行解析,然后转换为一个ApplicationListener,添加到ApplicationContext的applicationListeners属性中。
8.向BeanFactory中添加DefaultEventListenerFactory的BeanDefinition。
DefaultEventListenerFactory是支持EventListener注解的EventListenerFactory的默认实现,用于创建ApplicationListener。

2.1.3 设置ClassPathBeanDefinitionScanner

        构造ClassPathBeanDefinitionScanner(用于扫描得到并注册BeanDefinition),并进行相关设置。涉及的步骤如下代码所示:

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
       Environment environment, @Nullable ResourceLoader resourceLoader) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
    // 设置默认的includeFilters
    if (useDefaultFilters) {
       registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}

其中,registerDefaultFilters()方法中设置了扫描时默认需包含的注解,涉及:
Component
javax.annotation.ManagedBean
javax.inject.Named

2.2 register(Class<?>... componentClasses)

通过reader将Config的BeanDefinition进行注册,对应BeanDefinition类型为AnnotatedGenericBeanDefinition。

2.3 refresh()

refresh()方法主要分为三个阶段,分别为context初始化前准备、context初始化、context初始化完成后收尾,整体流程如下图所示:

接下来,我们将详细分析三个阶段中所涉及的相关内容。

2.3.1 context初始化前准备

        当前阶段涉及三个子流程,分别为:prepareRefresh()-context刷新前的准备工作、obtainFreshBeanFactory()-通知子context刷新BeanFactory并获取当前context内部的BeanFactory、prepareBeanFactory(beanFactory)-对当前context的BeanFactory的属性进行配置。

2.3.1.1 prepareRefresh()

        context刷新前的准备工作,设置启动时间、活动状态标志,执行所有property source的初始化,应用程序监听器、事件的保存集合创建。执行步骤如下:

1.设置启动时间startupDate为当前时间;

2.设置关闭状态closed为false;

3.设置活动状态标志active为true;

4.初始化context的environment的占位属性,允许子类context设置一些属性到environment中;

5.校验environment中的标记为必填的属性是否都可解析(是否有值);

6.存储预刷新的应用程序监听器,添加到earlyApplicationListeners、applicationListeners属性中;

7.创建集合保存早期事件。

2.3.1.2 obtainFreshBeanFactory()

        通知子context刷新BeanFactory,并获取当前context内部的BeanFactory。执行步骤如下:

1.refreshBeanFactory()

子类的扩展点,子类可通过此方法执行实际配置的加载。

当前类AnnotationConfigApplicationContext继承了GenericApplicationContext对该方法的实现,该方法将容器的refreshed属性设置为true,并给持有的beanFactory设置的序列化ID。

2.getBeanFactory()

通过调用实现了此方法的子类方法获取context内部持有的BeanFactory,对应类型为ConfigurableListableBeanFactory。

2.3.1.3 prepareBeanFactory(beanFactory)

        对当前context的BeanFactory的属性进行配置,例如context的ClassLoader和post-processors(后置处理器)。执行步骤如下:

1.设置BeanFactory的ClassLoader;

2.设置表达式解析器:StandardBeanExpressionResolver,用于解析Spring中的表达式;

3.添加PropertyEditorRegistrar:ResourceEditorRegistrar,是PropertyEditor的注册器,用于注册一些默认的PropertyEditor;

4.添加Bean的后置处理器:ApplicationContextAwareProcessor,用来执行EnvironmentAware、ApplicationContextAware、ApplicationStartupAware等的回调方法;

5.添加ignoreDependencyInterface:添加接口,如果有类实现了这些接口,并且类的set方法在接口中也存在,那么这个set方法在自动注入的时候将不会执行,例如ApplicationContextAware这个接口,如果子类实现了这个接口,则必须实现setApplicationContext方法,该方法只有在回调Aware接口时才会执行。(注意:不对@Autowired注解生效);

添加的接口有:

EnvironmentAware

EmbeddedValueResolverAware

ResourceLoaderAware

ApplicationEventPublisherAware

MessageSourceAware

ApplicationContextAware

ApplicationStartupAware

6.添加resolvableDependencies:在使用byType注入时,会从这个属性里根据类型找Bean。添加的内容有:

BeanFactory.class:当前BeanFactory对象

ResourceLoader.class:当前ApplicationContext对象

ApplicationEventPublisher.class:当前ApplicationContext对象

ApplicationContext.class:当前ApplicationContext对象

7.添加BeanPostProcessor:ApplicationListenerDetector。

ApplicationListenerDetector是一个BeanPostProcessor,用来判断某个Bean是否为ApplicationListener,若是则添加到ApplicationContext中,对应方法为postProcessAfterInitialization,该方法中判断了ApplicationListener只能为单例,否则将不追加到context中。

8.添加BeanPostProcessor:LoadTimeWeaverAwareProcessor,

LoadTimeWeaverAwareProcessor是一个BeanPostProcessor,用来判断某个Bean是否实现了LoadTimeWeaverAware接口,如果实现了则把ApplicationContext中的loadTimeWeaver回调setLoadTimeWeaver方法设置给该Bean。

9.注册默认的环境相关的单例Bean

environment:ConfigurableEnvironment对象

systemProperties:System.getProperties()返回的Map对象

systemEnvironment:System.getenv()返回的Map对象

applicationStartup:实现了ApplicationStartup接口的DefaultApplicationStartup对象

2.3.2 context初始化

        当前阶段涉及9个子流程,接下来将逐步分析每个子流程中涉及的内容。

2.3.2.1 postProcessBeanFactory(beanFactory)

        ApplicationContext子类的扩展点,用于子类给BeanFactory注册一些特殊的BeanPostProcessors.

2.3.2.2 invokeBeanFactoryPostProcessors(beanFactory)

        实例化在context中的工厂处理器(BeanFactoryPostProcessor)为Bean并按照给定顺序调用。此子流程分为两步,第一步为调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法,实例化涉及的BeanFactoryPostProcessor,并按顺序进行接口方法调用;第二步为给BeanFactory添加LoadTimeWeaverAwareProcessor。

2.3.2.2.1 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())

        此步骤代码虽然较多,但总结下来分为两部分:

第一部分为实例化实现了BeanDefinitionRegistryPostProcessor接口的Bean,对Bean进行排序(按照实现了PriorityOrdered接口、实现了Ordered接口、前两接口均未实现的顺序),并执行实现的postProcessBeanDefinitionRegistry()方法,此处实际执行的ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方法,该方法完成了Config类的解析、扫描得到BeanDefinition并注册、解析@Import和@Bean等注解得到BeanDefinition并注册,详见《Spring源码之BeanDefinition扫描创建注册流程

第二部分为实例化实现了BeanFactoryPostProcessor接口的Bean,对Bean进行排序(按照实现了PriorityOrdered接口、实现了Ordered接口、前两接口均未实现的顺序),并执行实现的postProcessBeanFactory()方法;

2.3.2.2.2 给BeanFactory添加LoadTimeWeaverAwareProcessor

        若执行到此处,发现beanFactory中存在名为loadTimeWeaver的Bean,则添加名为LoadTimeWeaverAwareProcessor的BeanPostProcessor,并设置TempClassLoader为ContextTypeMatchClassLoader。

2.3.2.2.3 registerBeanPostProcessors(beanFactory)

        实例化拦截[Bean创建]的BeanPostProcessor并按照给定顺序注册,整体步骤如下所示:

1.向BeanFactory的beanPostProcessors集合中添加BeanPostProcessorChecker实例,用来检查Bean是否初始化完成,如果没有执行所有的 beanPostProcessor(用beanPostProcessors的数量来判断),则会打印一行info日志;

2.根据BeanPostProcessor实现的接口进行分组,分组规则为是否实现了接口:PriorityOrdered、Ordered、无、MergedBeanDefinitionPostProcessor,组内根据设置的优先级进行排序;

3.按优先级为:PriorityOrdered、Ordered、无、MergedBeanDefinitionPostProcessor 将BeanPostProcessor添加到BeanFactory的beanPostProcessors中;

4.重新向BeanFactory的beanPostProcessors集合中添加ApplicationListenerDetector实例,保证其在末尾。ApplicationListenerDetector重新了equals和hashCode方法,确保实例不会被重复添加。

2.3.2.2.4 initMessageSource()

        初始化当前context的MessageSource。如果BeanFactory中存在一个叫messageSource的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的messageSource属性;若不存在则实例化一个类型为DelegatingMessageSource的对象赋值给ApplicationContext的messageSource属性。让ApplicationContext拥有国际化的功能,消息绑定,消息解析。

2.3.2.2.5 initApplicationEventMulticaster()

        初始化当前context的事件派发器。如果BeanFactory中存在一个叫applicationEventMulticaster的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的applicationEventMulticaster属性;若不存在则实例化一个类型为SimpleApplicationEventMulticaster的对象赋值给ApplicationContext的applicationEventMulticaster属性。让ApplicationContext拥有事件发布的功能。

2.3.2.2.6 onRefresh()

        AbstractApplicationContext提供给子类的扩展点,初始化特殊context子类的特殊Bean。当前未做具体实现。

2.3.2.2.7 registerListeners()

        检查事件监听器,并进行注册。步骤如下:

1.首先将特殊的静态事件监听器进行注册,来自于ApplicationContext的applicationListeners属性;

2.将BeanFactory中实现了ApplicationListener接口的事件监听器的Bean名称获取到,通过Bean名称进行注册;

3.发布早期事件,来自于ApplicationContext的earlyApplicationEvents属性。

2.3.2.2.8 finishBeanFactoryInitialization(beanFactory)

        完成当前context的Bean Factory的初始化,并实例化剩余所有的非懒加载单例Bean。整体步骤如下所示:

1.设置BeanFactory的conversionService属性。如果BeanFactory中存在一个叫conversionService的BeanDefinition,且对应类的类型为ConversionService,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的lifecycleProcessor属性;

ConversionService是Spring3.0添加的一个属性值转换类,用于替代JavaBeans的PropertyEditors。

2.如果BeanFactory的embeddedValueResolvers为空,即不存在绑定配置值的解析器BeanFactoryPostProcessor,例如PropertySourcesPlaceholderConfigurer,则设置一个默认的解析器,主要用于解析注解属性的值;

3.如果BeanFactory中存在Bean类型为LoadTimeWeaverAware的Bean名称,则获取到并进行实例化;

4.将BeanFactory的tempClassLoader属性置空;

5.冻结Bean Definition相关元数据,不在变动,便于后续清空不必要的缓存;

6.实例化所有非懒加载的单例Bean(重点)

beanFactory.preInstantiateSingletons();

该步骤涉及Bean的实例化、依赖注入、初始化、AOP,以及循环依赖等内容,单独进行分析。

2.3.2.2.9 finishRefresh()

        完成当前context的刷新,调用LifecycleProcessor的onRefresh()方法,发布ContextRefreshedEvent。整体步骤如下所示:

1.清除上下文级资源缓存;

2.初始化ApplicationContext的lifecycleProcessor属性。如果BeanFactory中存在一个叫lifecycleProcessor的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的lifecycleProcessor属性;若不存在则实例化一个类型为DefaultLifecycleProcessor的对象赋值给ApplicationContext的lifecycleProcessor属性,并调用BeanFactory的registerSingleton()方法进行注册。

3.通过步骤2中的初始化的LifecycleProcessor,获取所有实现了Lifecycle接口的Bean,调用其start()方法,传播context的刷新;

4.创建并发布ContextRefreshedEvent事件。

2.3.3 context初始化完成后收尾

        重置Spring的公共反射元数据缓存,涉及缓存如下:

ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值