dcddc

西米大人的博客

0%

系统学习Spring源码-Spring容器

前言

在讲 beanFactory 架构时说过,接口ConfigurableBeanFactory表明 bean 工厂是可配置的,为了让用户能方便的配置 bean 工厂,Spring 设计了代表 Spring 容器的顶级接口ApplicationContext。如果说 bean 工厂负责管理 bean 的生命周期,提供的扩展能力是对 bean 的定制,那么 Spring 容器则站在更高的维度,提供对 bean 工厂的定制能力以及应用维度的事件发布和消费能力等:

  • 支持多种 Spring 配置方式来构建 beanFactory
  • 轻松定制 beanFactory
  • 支持应用事件广播和监听

ApplicationContext 架构

基础类

ApplicationContext

顶层接口,用来指代一个 Spring 容器,getAutowireCapableBeanFactory方法用来获取一个可依赖注入的 bean 工厂,可见 Spring 容器的核心就是包了一个基础的 bean 工厂

ConfigurableApplicationContext

继承ApplicationContext,描述一个可配置 beanFactory 的 Spring 容器,定义配置方法,例如添加 bfppaddBeanFactoryPostProcessor、添加应用事件监听器addApplicationListener

  • 类比ConfigurableBeanFactory,描述的是可配置的 bean 工厂,实现对 bean 加载过程的定制,例如给 bean 工厂配置 bpp。对于 Spring 容器而言,它的可配置体现在对 bean 工厂本身的定制化,因此提供的扩展是 bean 工厂处理器 bfpp。需要说明的是,bfpp 虽然定制的是 bean 工厂,但最终还是通过 bean 工厂影响 bean,本质上还是对 bean 加载过程的定制

定义核心方法refresh,用来刷新(初始化)Spring 容器。大部分具体的 Spring 容器实现类都会在构造函数里调用该方法实现容器的初始化
定义核心方法close,关闭 Spring 容器时调用

AbstractApplicationContext

ConfigurableApplicationContext的实现类,描述了一个可配置的 Spring 容器,它做到了这些事情:

  • 可添加 bfpp、应用事件监听器
  • 实现了refresh方法,框定了 Spring 容器初始化的流程,该方法的实现后面会详细介绍
  • 实现了close方法,框定了 Spring 容器关闭的流程,执行所有单例 bean 的销毁生命周期

ConfigurableApplicationContext 在 refresh 方法里定义了一些模板方法,需要子类在容器初始化过程中做这些事情:

  • 实现模板方法refreshBeanFactory,构建一个 DefaultListableBeanFactory。根据对该方法的不同实现方式,可以将子类容器分为两大类,Refreshable 的容器和 Generic 的容器,区别是 Refreshable 容器真正实现了该模板方法,所以每次调用 refresh 方法,都会重新构建 bf,而 Generic 容器做了个空实现,实际在构造函数里先构建好 bf,所以调用 refresh 方法不会再重新构建 bf
  • 实现模板方法closeBeanFactory,Spring 容器关闭时调用。这个目前子类容器也没有特殊的实现
  • 实现模板方法postProcessBeanFactory,容器初始化过程中后置处理构建好的 bf

核心类

ClassPathXmlApplicationContext

基于 XML 构建 bf 的 refreshable 的 Spring 容器,实现 refreshBeanFactory 方法,每次调用 refresh 都会基于 xml 构建 bf

AnnotationConfigWebApplicationContext

基于注解构建 bf 的 refreshable 的 Spring 容器,实现 refreshBeanFactory 方法,每次调用 refresh 都会基于 配置类 构建 bf

GenericXmlApplicationContext

基于 XML 构建 bf 的 generic 的 Spring 容器,refreshBeanFactory 方法做空实现,构造函数里基于 xml 构建 bf,调用 refresh 不会再次构建 bf

AnnotationConfigApplicationContext

基于 注解 构建 bf 的 generic 的 Spring 容器,refreshBeanFactory 方法做空实现,构造函数里基于 配置类 构建 bf,调用 refresh 不会再次构建 bf

基于注解构建 bf 的说明

如果是基于注解的 Spring 容器,无论是 refreshable 的还是 generic 的,注册业务 bean 的 bd 前,都会提前向 bf 注册支持注解驱动的一些内部 bean 的 bd,重点有这么几个 bean:

  • ConfigurationClassPostProcessor
    • 负责注册通过配置类 bean(@Configuration 修饰)间接定义的所有 bd 到 bf
  • AutowiredAnnotationBeanPostProcessor
    • bpp,依赖注入阶段加载并注入@Autowired 修饰的 bean,解析得到@Value 的实际值并注入到成员变量
  • CommonAnnotationBeanPostProcessor
    • bpp,依赖注入阶段加载并注入@Resource 修饰的 bean

see:org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

总结

ApplicationContext 架构的 UML 类图:

综上,ApplicationContext架构主要使用了适配器模式模板模式

  • ApplicationContext通过在内部持有一个DefaultListableBeanFactory,适配了 BeanFactory 接口
  • Spring 容器的刷新主流程在上层抽象类的 refresh 方法中实现。同时定义创建 bean 工厂的模板方法refreshBeanFactory,有两套 bean 工厂创建流程,分别由子类AbstractRefreshableApplicationContextGenericApplicationContext实现
    • AbstractRefreshableApplicationContext类和GenericApplicationContext类都有自己的子类,分别支持 xml 方式和注解方式的 beanDefinition 注册

初始化 Spring 容器

容器在实例化完成后,一般会接着调用 refresh 方法初始化,或者直接在构造函数里就调用 refresh 方法,下面详述容器初始化流程

定制系统变量

回调模板方法initPropertySources,由三方实现,可以添加系统变量、设置哪些系统变量是必须的(不存在直接抛异常)

1
2
3
4
5
6
// Initialize any placeholder property sources in the context environment.
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
1
2
3
4
5
6
7
8
9
10
11
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
for (String key : this.requiredProperties) {
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}

测试代码:applicationcontext.RequiredPropertyTest

构建 DefaultListableBeanFactory

构建 Spring 容器的 DefaultListableBeanFactory,提供refreshBeanFactory模板方法,由子类实现,创建一个已经完成 beanDefinition 解析和注册的 bean 工厂。上面说过,只有 refreshable 的 Spring 容器在这里构建 bf

1
2
3
4
5
6
7
8
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

显式配置 DefaultListableBeanFactory

注册 SPEL 解析器

显式注册解析 SpEL 的StandardBeanExpressionResolver,该 resolver 会在 bean 属性赋值前被调用来解析配置属性的 SpEL 表达式

1
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

注册属性编辑注册器

显式注册ResourceEditorRegistrar,注册器会在 Bean 加载阶段被调用,给 BeanWrapper 注册一些 IO 类型的PropertyEditor

1
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   @Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, ContextResource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

ClassLoader classLoader = this.resourceLoader.getClassLoader();
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
}
}

如果用户想添加自定义的PropertyEditor,可以简单覆盖PropertyEditorSupportsetAsText方法来自定义一个PropertyEditor,再创建它的注册器PropertyEditorRegistrar,然后配置一个CustomEditorConfigurerBean,在 propertyEditorRegistrars 属性中加入这个 Registrar。CustomEditorConfigurer是 bfpp,在 beanFactory 后置处理中将PropertyEditorRegistrar注册到 BeanFactory

注册 ApplicationContextAwareProcessor

显式注册 bpp:ApplicationContextAwareProcessor,它的作用是 bean 前置初始化时,为 bean 自动注入 Aware 方式指定的 Spring 容器组件

1
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}

注册 ApplicationListenerDetector

显式注册 bpp:ApplicationListenerDetector,作用是对于类型为ApplicationListener子类的 bean,后置初始化处理时注册到 ApplicationContext。这些应用事件监听器最终会被注册到事件组播器ApplicationEventMulticaster。Spring 容器关闭时,ApplicationListenerDetector会在 bean 销毁前置回调时,将其从ApplicationEventMulticaster里移除

1
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
...
}
}
return bean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
// ApplicationEventMulticaster not initialized yet - no need to remove a listener
}
}
}

注册 environment 相关 bean 到 BeanFactory

注册 ConfigurableEnvironment 到 bf
通过 environment 可以拿到 map 类型的 JVM 参数和系统环境变量,这两个 map 也一并注册到 bf

1
2
3
4
5
6
7
8
9
10
11
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
// JVM参数
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
// 环境变量
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}

后置处理 bf

提供模板方法后置处理 bf

提供模板方法 postProcessBeanFactory,由AbstractApplicationContext的子类(可由用户实现)覆写,后置处理 beanFactory

1
postProcessBeanFactory(beanFactory);

调用 bfpp 执行 bean 工厂后置处理

bfpp 的来源

1、调用方法addBeanFactoryPostProcessor显式注册到 AbstractApplicationContext

  • 注意,Spring 提供的容器没有调该方法添加任何 bfpp,可以理解为是给用户自定义容器用的。但要保证该方法必须在 refresh 方法前被调用,否则不起作用
1
2
3
4
5
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}

2、通过 bd 走 bean 加载流程得到的 bfpp。AbstractApplicationContext会从 bf 的全局 bd 里枚举 bfpp 的 beanName,然后加载 bfpp

  • 这细分为两类,一类是用户自己注册的 BeanFactoryPostProcessor bean,另一类是 Spring 注册内部的 bfpp 的 bd 到 bf,ConfigurationClassPostProcessor就是这种方式注册的
1
2
3
4
5
postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
... ...
beanPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}

bfpp 的调用顺序

1、调用显式注册的BeanDefinitionRegistryPostProcessor的子类的postProcessBeanDefinitionRegistry方法

  • BeanDefinitionRegistryPostProcessor 是 bfpp 的子接口,定义postProcessBeanDefinitionRegistry方法,预处理 bd
1
2
3
4
5
6
7
8
9
10
11
         for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}

2、加载并调用 bd 注册到 bf 的BeanDefinitionRegistryPostProcessor的子类的postProcessBeanDefinitionRegistry方法

  • 优先排序并执行实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor
    • 排序使用的 comparator:AnnotationAwareOrderComparator
  • 排序执行实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor
  • 排序执行剩下的 BeanDefinitionRegistryPostProcessor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行Spring注册的BeanDefinitionRegistryPostProcessor,这里会执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 因为ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry会注册从ConfigurationBean发现的所有bean
// 所以需要筛选出新增的BeanDefinitionRegistryPostProcessor,调用它的postProcessBeanDefinitionRegistry
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}

3、调用 BeanDefinitionRegistryPostProcessor 子类的 postProcessBeanFactory 方法,后置处理 bfpp

1
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

4、调用显示注册的 bfpp 的 postProcessBeanFactory 方法,后置处理 bfpp

1
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

5、加载并调用 bd 注册到 bf 的 bfpp 的 postProcessBeanFactory 方法,后置处理 bfpp

  • 会 skip 上面已经调用过的 BeanDefinitionRegistryPostProcessor 子类和显示注册的 bfpp
  • 依然是先排序后执行,优先 PriorityOrdered,其次 Ordered,再次剩下的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
      String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

bfpp 的应用场景举例

ConfigurationClassPostProcessor

  • 它是BeanDefinitionRegistryPostProcessor的子类。基于注解的 Spring 容器会在构建 bf 阶段将 bd 注册进去。它的 postProcessBeanDefinitionRegistry 方法负责把配置类 bean 间接引入的所有 bean 的 bd 注册到 bf

CustomEditorConfigurer

  • 用户可以配置这个 bean,bf 后置处理阶段,间接注册一组自定义的PropertyEditorRegistrar到 bf
  • 测试代码:populatebean.propertyeditor.PropertyEditorTest

PropertySourcesPlaceholderConfigurer

  • Spring 解析标签”context:property-placeholder”,注册 PPC:PropertySourcesPlaceholderConfigurer。bf 后置处理阶段,将 bd.pv 里定义的占位符替换为实际值
    • 占位符替换优先级:JVM 参数->系统环境变量->应用配置文件
  • 测试代码:populatebean.value.ValueTest#testPPC

加载并添加配置的 bpp 到 bf

bpp 的来源只能通过配置方式,这也体现了 Spring 容器的定位,是面向 bf,而非面向 bean,所以如果需要 bpp,只能配置,不能直接通过 Spring 容器添加

  • 优先注册实现了PriorityOrderedOrdered接口的 bpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
... ...
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);
}
}
... ...
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
... ...
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
... ...
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

AutowiredAnnotationBeanPostProcessor

基于注解的 Spring 容器,例如AnnotationConfigApplicationContext,在构造函数里就会给 bf 注册AutowiredAnnotationBeanPostProcessor的 bd,然后在这个阶段加载并将其添加到 bf。该 bpp 的作用是在 bean 加载的依赖注入阶段,解析得到@Value 的实际值或者加载@Autowired 修饰的 依赖 bean,并反射注入

  • 对于@Value,如果使用占位符,使用 StringValueResolver 来解析,如果使用 spel,使用 Spring 容器的 spel 解析器来解析

获取并添加应用事件组播器 ApplicationEventMulticaster 到 Spring 容器

如果 bf 有组播器的 bd,即用户注册了一个自己的组播器 bean,则直接加载后作为 Spring 容器的应用事件组播器。否则 new 一个 Spring 提供的默认组播器SimpleApplicationEventMulticaster

  • Spring 容器发布应用事件时使用组播器,它通过观察者模式组播应用事件给注册到它的事件监听器
1
2
3
4
5
6
7
8
9
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}

SimpleApplicationEventMulticaster

作为 Spring 容器默认的事件组播器,有如下特性:

  • 如果 set 线程池,回调监听器的任务提交到线程池中执行

  • 会筛选与应用事件匹配的ApplicationListener,再回调来处理事件,筛选规则是:

    • 如果ApplicationListenerGenericApplicationListener,调用它的 supportsEventType 和 supportsSourceType 判断事件类型和事件载体类型是否满足
    • 否则,使用适配器模式包装成一个GenericApplicationListenerAdapter。如果ApplicationListenerSmartApplicationListener,调用它的 supportsEventType 和 supportsSourceType 判断事件类型和事件源对象类型是否满足,否则,只要ApplicationEvent的类型为 ApplicationListener 泛型指定事件类型或子类型即可
1
2
3
4
5
6
7
   protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {

GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

测试代码:applicationcontext.ApplicationListenerTest

将显式添加到容器的 ApplicationListener 添加到组播器

添加应用事件监听器ApplicationListener到组播器ApplicationEventMulticaster

  • ApplicationListener的来源渠道同 bfpp,显式添加到 Spring 容器 或配置为 bean。这里只将显式添加到 Spring 容器的 listener 注册到ApplicationEventMulticaster
    • 配置的 listener bean,通过前面介绍的 bpp:ApplicationListenerDetector,在 bean 后置初始化处理时添加到ApplicationEventMulticaster
1
2
3
4
5
6
7
8
9
10
11
12
protected void registerListeners() {
// 显式注册到Spring容器的监听器,注册到应用事件组播器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}

// 通过注册的BD走bean加载的监听器,beanName注册到应用事件组播器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
}

添加属性占位符解析器 StringValueResolver 到 bf

StringValueResolver 把@Value 注解表达式中的“占位符”替换为实际值。如果 bean 工厂不存在占位符解析器StringValueResolver,则添加一个 lambda 表达式实现的匿名 resolver 到 bf,底层使用PropertySourcesPropertyResolver解析@Value 注解表达式中的占位符

  • 注意,只有@Value 表达式用占位符,即”${xxx}”书写,才会依赖 StringValueResolver
  • 解析@Value 并注入是通过上面介绍的 bpp:AutowiredAnnotationBeanPostProcessor
  • 解析占位符用到的配置源包括:JVM 参数、系统环境变量、应用配置文件,优先级为
    • JVM 参数
    • 系统环境变量
    • 应用配置文件
1
2
3
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

PropertySourcesPlaceholderConfigurer

如果 Spring 容器基于 XML 配置,且通过标签”context:property-placeholder”注册了PropertySourcesPlaceholderConfigurer,在 bf 后置处理时,就会添加一个 Lambda 写的匿名StringValueResolver到 bf,同时解析并替换 bd.pv 中的占位符。因此,上面判断 beanFactory.hasEmbeddedValueResolver() 就返回 true,不会再次添加 StringValueResolver

PropertySourcesPlaceholderConfigurer 给 bf 添加的 StringValueResolver 的配置源可以包含额外指定的应用配置文件

除了 xml 方式注册 PropertySourcesPlaceholderConfigurer,因为它就是一个 bfpp,所以也可以用户自己将其配置成 bean,添加一些 k-v 或者直接为 location 设置应用配置文件资源,作为配置源

测试代码:

  • populatebean.value.ValueTest#testPPC2
  • org.springframework.context.support.PropertySourcesPlaceholderConfigurerTests#replacementFromEnvironmentProperties
  • org.springframework.context.support.PropertySourcesPlaceholderConfigurerTests#localPropertiesViaResource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.propertySources == null) {
this.propertySources = new MutablePropertySources();
if (this.environment != null) {
this.propertySources.addLast(
new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
@Override
@Nullable
public String getProperty(String key) {
return this.source.getProperty(key);
}
}
);
}
try {
PropertySource<?> localPropertySource =
new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
if (this.localOverride) {
this.propertySources.addFirst(localPropertySource);
}
else {
this.propertySources.addLast(localPropertySource);
}
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}

processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
this.appliedPropertySources = this.propertySources;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
final ConfigurablePropertyResolver propertyResolver) throws BeansException {

propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
propertyResolver.setValueSeparator(this.valueSeparator);

StringValueResolver valueResolver = strVal -> {
String resolved = (this.ignoreUnresolvablePlaceholders ?
propertyResolver.resolvePlaceholders(strVal) :
propertyResolver.resolveRequiredPlaceholders(strVal));
if (this.trimValues) {
resolved = resolved.trim();
}
return (resolved.equals(this.nullValue) ? null : resolved);
};

...
beanFactoryToProcess.embeddedValueResolvers.add(valueResolver);
}

如果没注册 PropertySourcesPlaceholderConfigurer,则 xml 的标签里指定的占位符不会被替换,因为依赖注入阶段不会对 bd.pv 中的 value 做占位符解析处理。测试代码:

  • populatebean.value.ValueTest

加载单例 beans

预加载所有非懒加载的单例到 beanFactory(好处是提前暴露 bean 配置的错误)

  • 如果加载的 bean 实现了SmartInitializingSingleton接口,加载后回调 afterSingletonsInstantiated 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
... ...
else {
getBean(beanName);
}
}
}

for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
... ...
smartSingleton.afterSingletonsInstantiated();
}
}

Spring 容器初始化后置处理

此时 Spring 容器初始化流程已经结束,接下来进行的是容器初始化后置处理

回调 SmartLifecycle Bean 的 start 方法

有些 bean 在 Spring 容器初始化完成后要执行一些生命周期钩子函数

如果用户注册了实现LifecycleProcessor接口的 bean,优先从 bd 获取并加载该 bean 作为 Spring 容器的生命周期处理器,否则创建默认的DefaultLifecycleProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
}
}

调用 LifecycleProcessor#onRefresh 方法,默认调用 DefaultLifecycleProcessor 的 onRefresh 方法,内部调用 startBeans 方法,参数 autoStartupOnly=true
该方法先将实现了SmartLifecycle接口的 bean 分组,然后按分组号排序后,从小到大以组为维度调用组内部 SmartLifecycle bean 的 start 方法

  • SmartLifecycle bean 的 isAutoStartup 方法必须返回 true,才会回调 start 方法
  • 如果调用 DefaultLifecycleProcessor#start 方法,参数 autoStartupOnly=false,会对所有的SmartLifecycleLifeclcyebean,分组后回调 start 方法
  • 通过Phased接口获得分组号,如果 SmartLifecycle bean 未实现该接口,则为 0 号
    • Spring 容器 close 时,按分组号从大到小回调 stop 方法,与 start 方法顺序相反
1
getLifecycleProcessor().onRefresh();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
// 优先启动所有Lifycycle bean依赖的lifecycle beans
for (String dependency : dependenciesForBean) {
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
try {
// 启动lifecycle bean
bean.start();
}
... ...
}
}
}

组播 Spring 容器初始化完成事件

通过ApplicationEventMulticaster组播ApplicationContext的刷新完成事件ContextRefreshedEvent到注册的ApplicationListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
publishEvent(new ContextRefreshedEvent(this));
... ...

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");

ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}

... ...
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
... ...
}

总结

综上,可以总结出 ApplicationContext 具备这些定制和扩展能力:

  • 支持 SPEL
    • 显式注册表达式解析器到 beanFactory
  • 支持自定义 bean 属性编辑器
    • 通过 bfpp 后置处理时把属性编辑注册器注册到 beanFactory
  • 支持自定义 BeanFactoryPostProcessor
    • 显式注册或配置方式自定义 bfpp
  • 支持自定义 BeanPostProcessor
    • 配置方式发现自定义 bpp
  • 支持自定义发布和监听应用事件
    • 配置方式自定义事件组播器,否则 Spring 容器提供默认的组播器
  • 支持 Spring 容器在启动或停止时刻回调 LifeCycle bean 对应的生命周期方法