【spring】 spring Application Context 以及 Application Context refresh 过程

从源码分析 spring application context 以及 application context 的 refresh 过程

介绍

application context 是 spring 应用的核心概念,它集多个概念于一身:

  • ListableBeanFactory: bean 容器
  • ResourceLoader: 资源加载器
  • ApplicationEventPublisher: spring 应用事件
  • MessageSource: 消息源,主要用于实现国际化
  • Environment: spring 运行环境与配置

每一个 spring 应用都至少有一个 application context。不同的场景会使用不同的具体实现,而不同的实现基本上是配置方式上的不同,所具有的特性基本上是一样的。

application context 还有层次结构。子 application context 会合并父 application context 的环境配置,响应在父 application context 发布的事件等。

类层次结构

application context 基本的类层次结构如下图:

application-context-class.jpg

  • ApplicationContext 接口就是 application context 的表示,它继承 EnvironmentCapable、 ListableBeanFactory 等多个接口(正好说明 application context 集合了多种概念)
  • ConfigurableApplicationContext 按照惯例,配置性的 set 方法都放在 Configurable 接口
  • AbstractApplicationContext 是 ApplicationContext 的抽象实现,使用模板方法设计模式,需要子类去实现具体的方法。它继承 DefaultResourceLoader,可以加载资源
  • GenericApplicationContext 不允许多次 refresh
  • AbstractRefreshableApplicationContext 允许多次 refresh

大部分场景所使用的 application context 都由 GenericApplicationContext 或 AbstractRefreshableApplicationContext 派生。例如: AnnotationConfigApplicationContext 由 GenericApplicationContext 派生, ClassPathXmlApplicationContext 由 AbstractRefreshableApplicationContext 派生。

GenericApplicationContext 和 AbstractRefreshableApplicationContext 都通过组合 DefaultListableBeanFactory 来实现 bean 容器的功能,区别是当多次 refresh 时, AbstractRefreshableApplicationContext 的 refreshBeanFactory 方法 (refresh 方法会调用到) 会重建 DefaultListableBeanFactory, 而 GenericApplicationContext 会报错。

refresh 过程

refresh 方法在 AbstractApplicationContext 类中定义,它是 application context 中最重要的方法。下面分析 refresh 的过程

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备 refresh
// 设置标志, 检查 Environment 是否有必要的属性, 设置 applicationListeners (有的话)
// 同时子类可以在这里设置额外的 PropertySources
prepareRefresh();

// 获取 beanFactory
// 如果是 AbstractRefreshableApplicationContext 子类,在这里会 refresh bean factory 并加载 BeanDefinition
// 加载 BeanDefinition 由子类的 loadBeanDefinitions 实现
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 给 beanFactory 设定一些固有的配置
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 空的实现,如果有需要,可以子类重载
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 调用 BeanFactoryPostProcessor (BFPP)
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
// 注册 BeanPostProcessors (BPP)
registerBeanPostProcessors(beanFactory);

// 初始化消息源
initMessageSource();

// 初始化事件广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 默认是空的
onRefresh();

// Check for listener beans and register them.
// 将 application context listener 放到 Event Multicaster
registerListeners();

// 实例化所有 non-lazy-init 的单例 bean
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 初始化 LifecycleProcessor: 如果 beanFactory 里有 lifecycleProcessor 这个 bean 就用这个 bean,否则就用 DefaultLifecycleProcessor
// 广播 ContextRefreshedEvent 事件
// 注册 LiveBeansView 这个 MBean,用来查看所有 bean
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

在 refresh 的过程中, 有几个地方需要详细说明

obtainFreshBeanFactory

在 obtainFreshBeanFactory 中会调用 refreshBeanFactory,而对于 AbstractRefreshableApplicationContext 子类,refreshBeanFactory 会调用子类的 loadBeanDefinitions 加载配置。例如 AbstractXmlApplicationContext 就是在这里加载 xml 并解析配置。

prepareBeanFactory

给 bean factory 设定默认的配置

  • class loader
  • BeanExpressionResolver:用来解析 spring 表达式
  • PropertyEditorRegistrar: 属性相关
  • 添加 ApplicationContextAwareProcessor, 这个 BPP 在 bean 实例化后给 bean 注入各类 Aware 属性
  • 添加 ApplicationListenerDetector, 这个 BPP 找出 ApplicationListener 类型的 bean 并注册到 application context
  • 如果有 loadTimeWeaver 的话就添加 BPP LoadTimeWeaverAwareProcessor 和 ClassLoader ContextTypeMatchClassLoader
  • 注册默认的 bean,包括
    • environment: application context 对应的 environment
    • systemProperties: 一个 Map
    • systemEnvironment: 一个 Map

invokeBeanFactoryPostProcessors

实例化并调用 BeanFactoryPostProcessors (BFPP)

这个时间点,bean 都还没有初始化(除了 BFPP 本身), BFPP 可以操作 beanFacotry 达到修改 bean 的定义,添加 bean 定义(BeanDefinitionRegistryPostProcessor 就是专门做这个) 等效果

BFPP 有两个来源,1 是 AbstractApplicationContext 的 beanFactoryPostProcessors 成员,可以通过编程的方式在 application context refresh 之前通过 addBeanFactoryPostProcessor 加入; 2 是 beanFactory 中注册的 BeanFactoryPostProcessor 类型的 bean。invokeBeanFactoryPostProcessors 的过程如下:

  1. 将第 1 类的 BFPP 按是不是 BeanDefinitionRegistryPostProcessor 分成两类 registryProcessors 和 regularPostProcessors, registryProcessors 里的调用它们的 postProcessBeanDefinitionRegistry
  2. 从 beanFactory 找出实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor,排序并调用它们的 postProcessBeanDefinitionRegistry 方法
  3. 将第 2 步找到的 BeanDefinitionRegistryPostProcessor 全部加入到 registryProcessors
  4. 从 beanFactory 找出实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor(排除第2步的),排序并调用它们的 postProcessBeanDefinitionRegistry 方法
  5. 将第 4 步找到的 BeanDefinitionRegistryPostProcessor 全部加入到 registryProcessors
  6. 从 beanFactory 找出 BeanDefinitionRegistryPostProcessor(排除第2,4步的),调用它们的 postProcessBeanDefinitionRegistry
  7. 将第 6 步找到的 BeanDefinitionRegistryPostProcessor 全部加入到 registryProcessors
  8. 调用 registryProcessors 里的 BFPP 的 postProcessBeanFactory
  9. 调用 regularPostProcessors 里的 BFPP 的 postProcessBeanFactory
  10. 从 beanFactory 找出 BFPP, 按 PriorityOrdered, Ordered 和 nonOrdered 分成 3 组,分别排序并调用 postProcessBeanFactory
  11. 清理元数据缓存

至此 invokeBeanFactoryPostProcessors 的过程结束

registerBeanPostProcessors

在 beanFactory 中找到所有 BPP, 按 PriorityOrdered、 Ordered 和 nonOrdered 分成 3 组,分别实例化并通过 beanFactory 的 addBeanPostProcessor 方法加入到 beanFactory

finishBeanFactoryInitialization

finishBeanFactoryInitialization 主要的作用是通过 beanFactory 的 preInstantiateSingletons 方法,实例化所有的非 non-lazy-init 的单例 bean。 preInstantiateSingletons 的过程如下

  1. 找到所有 singleton,非 abstract,非 lazy-Init 的 bean 的 beanName
  2. 对每个 beanName 调用 beanFactor (AbstractBeanFactory) 的 getBean ,如果 bean 还不存在,getBean 内部会调用 createBean 创建 bean
  3. 获取 BeanDefinition, 解析出 bean 的类型
  4. 如果 bean 是一个 InstantiationAwareBeanPostProcessor(BPP 的一个子类), 尝试调用它的 postProcessBeforeInstantiation 获得一个实例(Instantiation 是实例化),如果成功,调用这个 BPP 的 postProcessAfterInitialization 并返回这个 bean 作为 createBean 的结果
  5. 生成 bean 的实例对象,并用 BeanWrapper (方便使用)包装起来。 有多种方式生成 bean 实例对象,例如 Supplier,FactoryMethod,通过反射的方式调用 Constructor 等, 如果有 SmartInstantiationAwareBeanPostProcessor (InstantiationAwareBeanPostProcessorr 的子类)还可以通过它自动判断用哪个 Constructor
  6. 对这个 BeanDefinition (不是 bean )调用 MergedBeanDefinitionPostProcessor (BPP 的子类)的 postProcessMergedBeanDefinition 方法
  7. 在 populateBean 里设置 bean 的属性
    • 尝试调用 InstantiationAwareBeanPostProcessor (如有)的 postProcessAfterInstantiation 方法,如果 postProcessAfterInstantiation 返回 false, populateBean 就返回,不设置属性
    • 从 BeanDefinition 中获取 bean 的 PropertyValues
    • 尝试调用 InstantiationAwareBeanPostProcessor (如有)的 postProcessProperties 和 postProcessPropertyValues,这两个方法返回一个 PropertyValues 当作真正的 PropertyValues
    • 调用 applyPropertyValues 给 bean 设置属性
  8. populateBean 后调用 initializeBean 对 bean 进行初始化
    • 给 bean 应用 BeanNameAware 等 Aware 相关设定
    • 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
    • 调用 afterPropertiesSet 和 init 方法
    • 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
  9. 设置 DisposableBean

至此所有 non-lazy-init bean 初始化完成

FBPP 描述

1
2
3
4
5
6
// 允许客户修改 application context 的 bean definition
@FunctionalInterface
public interface BeanFactoryPostProcessor {
// 修改 bean definition
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
1
2
3
4
// 在一般的 BFPP 之前调用,用于 bean definition 注册
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

BPP 描述

1
2
3
4
5
6
7
8
9
10
11
// 可以修改新生成 bean, 例如检查注解,接口,将 bean 修改为 proxies
public interface BeanPostProcessor {

// 在 bean 初始化(例如 afterPropertiesSet 或 init 方法)之前调用,这时 bean 的属性已经被注入
// Initialization 是初始化
@Nullable
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

// 在 bean 初始化(例如 afterPropertiesSet 或 init 方法)之后调用
@Nullable
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 给 bean 实例化前后增加 callback
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

// bean 实例化之前被调用
// 如果返回值非 null,就用这个对象作为 bean
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

// bean 实例化之后被调用
// 如果返回 false, bean 就不会被注入属性
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

// bean 被注入属性前调用
// 如果返回值非 null,就用返回值做注入
PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException;

// Deprecated
// 作用同 postProcessProperties
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
1
2
3
4
5
6
7
8
9
10
11
12
// 可以修改 bean 的类型
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

// 返回 bean 的真正类型
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

// 返回 bean 的构造器
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

// 获取 EarlyBeanReference,用来解决循环引用
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}
1
2
3
4
5
6
7
8
9
// 可以合并 beanDefinition
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

// 给特定的 bean 合并 beanDefinition
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

// 如果 beanDefinition 被重置,就被调用
void resetBeanDefinition(String beanName);
}