# refresh详解
作者:Ethan.Yang
博客:https://blog.ethanyang.cn (opens new window)
相关源码参考: Spring源码中文注释仓库5.3.x分支 (opens new window)
经过上一章分析,不同类型的 IOC 容器在准备阶段和加载方式上略有差异,但最终都会调用抽象父类 AbstractApplicationContext 的 refresh() 方法进行容器刷新。下面是整体流程与核心逻辑。
ClassPathXmlApplicationContext.refresh()
│
└─ 调用父类 AbstractApplicationContext.refresh()
│
├─ 同步锁,防止并发刷新
│
├─ 【步骤1】prepareRefresh()
│ ├─ 初始化环境变量(Environment)
│ ├─ 记录启动时间戳
│ └─ 重置刷新状态相关标志
│
├─ 【步骤2 创建容器 (下一步详解)】obtainFreshBeanFactory()
│ ├─ 调用子类的 refreshBeanFactory(),重新加载 Bean 定义
│ └─ 返回新的 ConfigurableListableBeanFactory 实例
│
├─ 【步骤3】prepareBeanFactory(beanFactory)
│ ├─ 设置 ClassLoader
│ ├─ 添加 BeanPostProcessor(如 ApplicationContextAwareProcessor)
│ └─ 配置 PropertyEditor 注册
│
├─ 【步骤4】postProcessBeanFactory(beanFactory)
│ └─ 子类可重写扩展(通常空实现)
│
├─ 【步骤5】invokeBeanFactoryPostProcessors(beanFactory)
│ └─ 调用 BeanFactoryPostProcessor,支持 @Configuration、PropertySource 等处理
│
├─ 【步骤6】registerBeanPostProcessors(beanFactory)
│ └─ 注册 BeanPostProcessor,用于拦截 Bean 初始化流程(AOP、@Autowired 等)
│
├─ 【步骤7】initMessageSource()
│ └─ 初始化国际化资源管理器
│
├─ 【步骤8】initApplicationEventMulticaster()
│ └─ 初始化事件广播器,管理事件发布与监听
│
├─ 【步骤9】onRefresh()
│ └─ 子类模板方法,完成特定容器的刷新逻辑(如初始化生命周期Bean)
│
├─ 【步骤10】registerListeners()
│ └─ 注册事件监听器
│
├─ 【步骤11】finishBeanFactoryInitialization(beanFactory)
│ ├─ 初始化非懒加载单例 Bean
│ └─ 完成 Bean 实例化和依赖注入
│
├─ 【步骤12】finishRefresh()
│ ├─ 发布容器刷新完成事件
│ └─ 清理启动相关状态
│
└─ 异常处理
├─ 关闭已创建 Bean
└─ 取消刷新状态,抛出异常
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
核心设计与关键点
- 模板方法模式:
refresh()定义容器刷新完整流程,部分步骤留给子类实现。 - 线程安全:通过同步锁保证刷新过程不被多线程干扰。
- BeanFactory 重载:调用子类的
refreshBeanFactory(),确保每次刷新基于干净的 BeanFactory。 - 多阶段处理:
- 准备环境:
prepareRefresh() - 创建容器:
obtainFreshBeanFactory() - 配置 BeanFactory:
prepareBeanFactory() - 后处理 BeanFactory:
postProcessBeanFactory() - 调用 BeanFactoryPostProcessor:
invokeBeanFactoryPostProcessors() - 注册 BeanPostProcessor:
registerBeanPostProcessors() - 初始化核心组件:
initMessageSource()、initApplicationEventMulticaster() - 子类特定刷新:
onRefresh() - 注册事件监听器:
registerListeners() - 初始化非懒加载单例 Bean:
finishBeanFactoryInitialization() - 完成刷新:
finishRefresh()- 事件发布:刷新完成后发送事件,供组件监听容器生命周期。
- 异常安全:刷新异常时销毁已创建 Bean,保持容器状态一致。
- 准备环境:
refresh() 方法的核心作用是:
- 在创建新的 IOC 容器之前,如果已有旧容器存在,则先销毁并关闭旧容器,保证刷新后使用的是新创建的容器。
- 通过刷新流程,完成容器的初始化和 Bean 配置资源的加载。
- 该过程类似于对 IOC 容器的“重启”,确保新容器的状态是干净且完整的。
这样设计,保证了 Spring 容器的灵活性和可复用性,方便对容器进行多次刷新和重新加载。
# 1. prepareRefresh
容器准备阶段,准备刷新,设置环境、时间戳、标志位等, 比较简单, 读者自己阅读下相关源码。
# 2. obtainFreshBeanFactory
该方法用于获取或重建 IOC 容器,是 IOC 容器的核心实现。
# 核心流程
- 销毁旧容器
- 如果当前容器已有
BeanFactory,先销毁已有 Bean 并关闭旧 BeanFactory,释放资源,保证容器干净重建。
- 如果当前容器已有
- 创建新 BeanFactory
- 构造
DefaultListableBeanFactory实例,作为当前容器的 BeanFactory。
- 构造
- 配置 BeanFactory
- 设置序列化 ID (
setSerializationId) - 配置启动分析器 (
setApplicationStartup) - 根据容器配置自定义 BeanFactory(循环依赖、允许覆盖同名 Bean 等)
- 设置序列化 ID (
- 加载 Bean 定义
- 调用
loadBeanDefinitions(beanFactory),加载 XML 配置、注解扫描、Java 配置类等 Bean 定义。
- 调用
- 更新容器引用
- 将新创建并初始化的
BeanFactory赋值给当前上下文的beanFactory字段。
- 将新创建并初始化的
ClassPathXmlApplicationContext.refresh()
│
└─ AbstractApplicationContext.refresh()
│
├─ 【步骤2】obtainFreshBeanFactory()
│ │
│ ├─ 调用 refreshBeanFactory()
│ │ │
│ │ ├─ (AbstractRefreshableApplicationContext 实现)
│ │ │
│ │ ├─ if (hasBeanFactory())
│ │ │ ├─ destroyBeans() # 销毁已有 Bean 实例
│ │ │ └─ closeBeanFactory() # 关闭旧 BeanFactory
│ │ │
│ │ ├─ createBeanFactory()
│ │ │ └─ 创建新的 DefaultListableBeanFactory
│ │ │
│ │ ├─ beanFactory.setSerializationId(getId()) # 设置序列化ID
│ │ ├─ beanFactory.setApplicationStartup(...) # 设置启动分析器
│ │ ├─ customizeBeanFactory(beanFactory) # 自定义 BeanFactory(循环依赖、覆盖等)
│ │ ├─ (下一步详解) loadBeanDefinitions(beanFactory) # 加载 Bean 定义(XML、注解、Java配置)
│ │ └─ this.beanFactory = beanFactory # 设置当前上下文的 BeanFactory
│ │
│ └─ 返回新创建的 beanFactory
│
└─ 后续步骤(prepareBeanFactory...)
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
按照上述流程具体解析下源码:
# 载入配置路径
loadBeanDefinitions() 负责将配置文件转为 BeanDefinition:
- 创建读取器
XmlBeanDefinitionReader与当前BeanFactory绑定。
- 配置读取器
- 设置环境变量(
profile)、资源加载器、实体解析器(DTD/XSD 校验)。
- 设置环境变量(
- 初始化读取器扩展点
initBeanDefinitionReader()可由子类重写。
- 加载配置
- 优先尝试
Resource[] configResources,否则使用String[] configLocations(XML 路径)。
- 优先尝试
AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory)
│
├─ 创建 XmlBeanDefinitionReader(beanFactory)
├─ 配置 reader 属性(Environment、ResourceLoader、EntityResolver)
├─ initBeanDefinitionReader(reader)
└─ loadBeanDefinitions(reader)
├─ getConfigResources() → null
└─ getConfigLocations() → XML 路径数组
↓
reader.loadBeanDefinitions(configLocations)
2
3
4
5
6
7
8
9
10
# 路径处理策略
reader.loadBeanDefinitions(String... locations) 流程:
- 批量加载:遍历每个路径。
- 路径解析:
ResourcePatternResolver支持通配符 (classpath*:)- 普通路径直接解析为单个 Resource。
- 加载 Resource
- 委托给
XmlBeanDefinitionReader,解析 XML 并注册 BeanDefinition。
- 委托给
AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory)
│
├─ ... 看上节 ...
│
│
└─ 从这开始分析本节 AbstractXmlApplicationContext.loadBeanDefinitions(reader)
reader.loadBeanDefinitions(configLocations)
│
└─ AbstractBeanDefinitionReader.loadBeanDefinitions(String... locations)
├─ 遍历每个 location
│
├─ 调用 loadBeanDefinitions(String location)
│ │
│ ├─ 判断资源加载器是否实现 ResourcePatternResolver?
│ │ ├─ 是 → 使用 getResources(location) 获取多个 Resource
│ │ │ └─ PathMatchingResourcePatternResolver 默认支持
│ │ └─ 否 → 使用 getResource(location) 解析单个 Resource
│ │
│ └─ 对每个 Resource 调用 loadBeanDefinitions(Resource resource)
│ └─ (下一步详解)委托给 XmlBeanDefinitionReader 解析 XML 并注册 BeanDefinition
│
└─ 返回加载的 BeanDefinition 总数
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 解析 XML 内容
- 防止循环加载
- 使用
ThreadLocal<Set<EncodedResource>>记录当前线程正在加载的资源。
- 使用
- 封装资源
EncodedResource封装 Resource + encoding(如 UTF-8)。
- 解析入口
- 通过
InputSource标准化 SAX 输入,调用doLoadBeanDefinitions()。
- 通过
XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)
│
└─ new EncodedResource(resource)
↓
loadBeanDefinitions(EncodedResource encodedResource)
│
├─ 获取当前线程正在加载的资源 Set<EncodedResource>
│
├─ 检查是否已加载(避免循环加载)←────┐
│ └─ 若已存在则抛出异常 │
│ │
├─ try-with-resources 打开 InputStream │
│ └─ InputSource inputSource ←───────┘
│ ├─ 设置 encoding(如有)
│
├─ (下一步详解) 调用 doLoadBeanDefinitions(inputSource, resource)
│ └─ 执行真正的 XML 解析逻辑
│
└─ finally:从线程本地 Set 中移除资源,清理现场
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 文档对象准备
doLoadDocument()使用DocumentLoader(默认DefaultDocumentLoader)将 XML 转为 DOMDocument。DocumentBuilderFactory&DocumentBuilder设置验证、命名空间和实体解析器。- 返回标准 DOM
Document对象,为 BeanDefinition 注册提供结构化数据。
XmlBeanDefinitionReader.doLoadBeanDefinitions(inputSource, resource)
│
├─ doLoadDocument(inputSource, resource)
│ │
│ └─ documentLoader.loadDocument(...) ←────────────────────────────────────────────────────┐
│ │ │
│ ├─ 创建 DocumentBuilderFactory(根据校验模式和命名空间) │
│ │ └─ factory.setValidating(validationMode) │
│ │ └─ factory.setNamespaceAware(namespaceAware) │
│ │ │
│ ├─ 创建 DocumentBuilder(设置实体解析器和错误处理器) │
│ │ └─ builder.setEntityResolver(entityResolver) │
│ │ └─ builder.setErrorHandler(errorHandler) │
│ │ │
│ └─ builder.parse(inputSource) ←─────── 解析 XML 为 Document(DOM 树) ←────────────┘
│
└─ (下一步详解) registerBeanDefinitions(doc, resource) ←──── 注册 Bean 定义
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
至此,Spring 完成了配置文件的读取和 XML 的解析工作,获得了 DOM 结构的 Document 对象, 接下来将其交由 registerBeanDefinitions(doc, resource) 进行解析 <bean>、<import> 等标签,转换 BeanDefinition;
# 分配解析策略
关键点
- 委托模式设计
XmlBeanDefinitionReader负责整体流程管理;- 具体的 XML
<bean>结构解析交由DefaultBeanDefinitionDocumentReader; - 它内部再将解析细节委托给
BeanDefinitionParserDelegate。
这种设计便于扩展和维护,符合职责分离原则。
Document→ Spring BeanDefinition
Document是标准 XML 结构的 DOM;需要用 Spring 自定义规则(比如:
<bean>、<alias>)去解析并转为BeanDefinition;这就是
DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions()的职责。- 典型处理方式如下:
| XML 标签 | 处理逻辑简述 |
|---|---|
<bean> | 转为 BeanDefinition 对象并注册 |
<alias> | 调用 registry.registerAlias() |
<import> | 加载并递归解析其他 XML 配置文件 |
| 自定义标签 | 走命名空间解析器如 <context:component-scan> 等 |
- BeanDefinition 计数机制
- 在注册前后统计 BeanDefinition 的数量变化;
- 便于调试和日志记录,输出“新加载了多少个 bean 定义”。
XmlBeanDefinitionReader.registerBeanDefinitions(doc, resource)
│
├─ 创建 BeanDefinitionDocumentReader 实例(默认:DefaultBeanDefinitionDocumentReader)
│
├─ 获取当前容器已注册的 BeanDefinition 数量(countBefore)
│
└─ 调用 documentReader.registerBeanDefinitions(doc, createReaderContext(resource))
│
└─ DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(...)
│
├─ 提取 <beans> 根元素(root = doc.getDocumentElement())
│
└─ 调用 doRegisterBeanDefinitions(root) ←─────── 核心解析入口
│
└─ 创建 BeanDefinitionParserDelegate(解析委派器)
│
└─ (下一步详解)parseBeanDefinitions 解析 Bean 定义也就是xml标签
← 返回新注册的 BeanDefinition 数量 = 当前数量 - countBefore
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
实际解析逻辑由 DefaultBeanDefinitionDocumentReader 实现,通过委托给BeanDefinitionParserDelegate 处理具体元素解析。
Bean 配置资源的载入解析分为以下两个过程:
首先通过调用XML解析器将Bean配置信息转换得到Document对象, 但是这些Document并没有按照 Spring 的Bean 规则进行解析。这一步是载入的过程
其次,在完成通用的XML 解析之后,按照 Spring Bean 的定义规则对 Document 对象进行解析,其 解析过程是在接口 BeanDefinition DocumentReader DefaultBeanDefinitionDocumentReader 中实现.
# 解析xml对应的标签
关键点
parseBeanDefinitions- 入口,判断是否默认命名空间
- 默认命名空间时,遍历子元素并调用
parseDefaultElement - 非默认命名空间时,调用
parseCustomElement
parseDefaultElement- 根据标签名分发到具体处理逻辑:
<import>→ 加载其它配置资源<alias>→ 注册别名<bean>→ 解析Bean定义并注册<beans>→ 递归解析内部beans
- 根据标签名分发到具体处理逻辑:
parseCustomElement- 交给对应命名空间的
NamespaceHandler处理 - 处理自定义标签,生成BeanDefinition
- 交给对应命名空间的
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
│
├─ 判断 root 是否默认命名空间(delegate.isDefaultNamespace(root))
│
├─ 是默认命名空间:
│ │
│ ├─ 遍历 root 子元素,依次处理每个 XML 标签
│ │ │
│ │ ├─ 对每个子元素 ele 调用 parseDefaultElement(ele, delegate)
│ │ │
│ │ │ parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
│ │ │ │
│ │ │ ├─ 判断 ele 节点名称
│ │ │ │ │
│ │ │ │ ├─ 如果标签是 <import> → importBeanDefinitionResource(ele)
│ │ │ │ │ ├─ 读取 resource 属性,解析路径
│ │ │ │ │ ├─ 加载对应的外部 XML 资源
│ │ │ │ │ ├─ 递归调用 registerBeanDefinitions 加载新资源
│ │ │ │ │ └─ 合并 BeanDefinitions,发布 Import 事件
│ │ │ │ │
│ │ │ │ ├─ 如果标签是 <alias> → processAliasRegistration(ele)
│ │ │ │ │ ├─ 读取 name 和 alias
│ │ │ │ │ ├─ 校验并注册别名到容器
│ │ │ │ │ └─ 发布 Alias 注册事件
│ │ │ │ │
│ │ │ │ ├─ 如果标签是 <bean> → processBeanDefinition(ele, delegate)
│ │ │ │ │ ├─ 解析 id、class、scope 等属性,生成 BeanDefinition
│ │ │ │ │ ├─ 解析 constructor-arg、property 等子元素
│ │ │ │ │ ├─ 注册 BeanDefinition 到容器
│ │ │ │ │ ├─ 处理别名,发布注册事件
│ │ │ │ │ └─ 触发后置处理器和扩展点
│ │ │ │ │
│ │ │ │ └─ 如果标签是 <beans> → (下一步详解)递归调用 doRegisterBeanDefinitions(ele)
│ │ │ │
│ │ │ └─ 返回处理结果
│ │ │
│ │ └─ 继续处理下一个子节点
│ │
│ └─ 遍历结束,完成所有默认命名空间标签处理
│
└─ 否(自定义命名空间):
│
└─ 调用 delegate.parseCustomElement(root)
│
├─ 根据自定义标签的 namespace 和 localName,选择对应的 NamespaceHandler
│
├─ 交由 NamespaceHandler 解析
│
├─ 生成对应的 BeanDefinition
│
├─ 注册到容器
│
└─ 发布事件
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
# BeanDefinition注册
解析完成后, 开始进行BeanDefinition注册
processBeanDefinition()
│
└─ 调用 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry)
│
├─ 获取 beanName 和 BeanDefinition
│
├─ 调用 registry.registerBeanDefinition(beanName, beanDefinition)
│ │
│ ├─ 参数校验(beanName 非空,beanDefinition 非 null)
│ │
│ ├─ 如果是 AbstractBeanDefinition 类型,调用 validate() 进行合法性校验
│ │ └─ 校验失败抛出 BeanDefinitionStoreException
│ │
│ ├─ 查询已有的 BeanDefinition (existingDefinition = beanDefinitionMap.get(beanName))
│ │
│ ├─ 判断是否已有同名 BeanDefinition
│ │ ├─ 如果存在
│ │ │ ├─ 判断是否允许覆盖
│ │ │ │ ├─ 不允许覆盖,抛出 BeanDefinitionOverrideException
│ │ │ │ ├─ 允许覆盖且新定义权限更高,打印 info 日志
│ │ │ │ ├─ 允许覆盖且新旧定义不等,打印 debug 日志
│ │ │ │ └─ 允许覆盖且新旧定义相等,打印 trace 日志
│ │ │ └─ 使用新的 BeanDefinition 覆盖旧的
│ │ │
│ │ └─ 结束
│ │
│ └─ 如果不存在同名 BeanDefinition
│ ├─ 判断容器是否启动
│ │ ├─ 启动后,加锁更新 beanDefinitionMap 和 beanDefinitionNames
│ │ └─ 未启动,直接更新数据结构
│ ├─ 移除手动注册的单例名称(防止冲突)
│ └─ 清空冻结的 BeanDefinition 名称缓存
│
├─ 注册完成后
│ ├─ 若覆盖了已有 BeanDefinition 或同名单例存在,调用 resetBeanDefinition(beanName) 重置缓存
│ ├─ 否则,若配置冻结,则清理类型缓存 clearByTypeCache()
│ └─ 结束
│
├─ 返回,注册完成
│
└─ BeanDefinitionReaderUtils.registerBeanDefinition 完成所有别名的注册
├─ 遍历别名数组 aliases
└─ 依次调用 registry.registerAlias(beanName, alias)
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
至此,Bean 配置信息中配置的 Bean 被解析过后,已经注册到IOC 容器中,被容器管理起来,真正完 成了IOC 容器初始化。
# 3. prepareBeanFactory
prepareBeanFactory(beanFactory)
│
├─ 设置类加载器(BeanClassLoader)
│
├─ 设置表达式解析器(SpEL → StandardBeanExpressionResolver)
│
├─ 注册属性编辑器(ResourceEditorRegistrar)
│
├─ 添加 ApplicationContextAwareProcessor
│ └─ 回调 Bean 的 *Aware 接口方法
│
├─ 忽略部分 Aware 接口的普通依赖注入
│ ├─ EnvironmentAware
│ ├─ ResourceLoaderAware
│ ├─ ApplicationEventPublisherAware
│ ├─ MessageSourceAware
│ └─ ApplicationContextAware
│
├─ 注册可解析依赖(ResolvableDependency)
│ ├─ BeanFactory → 当前 BeanFactory
│ ├─ ResourceLoader → ApplicationContext
│ ├─ ApplicationEventPublisher → ApplicationContext
│ └─ ApplicationContext → 当前 ApplicationContext
│
├─ 添加 ApplicationListenerDetector
│ └─ 自动识别并注册 ApplicationListener
│
└─ 注册内置 Bean
├─ environment
├─ systemProperties
└─ systemEnvironment
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
需要关注 Aware 接口(如 BeanNameAware、ApplicationContextAware、EnvironmentAware):
- 在 Bean 初始化阶段,容器会回调这些接口的方法。
- 作用是 为 Bean 注入运行所需的基础设施对象,使 Bean 能够获取自身依赖的环境或容器资源。
# 4. postProcessBeanFactory
在 AbstractApplicationContext 中是 空方法,专门留给子类扩展,是 容器级别的扩展点。
- 作用:提供一个 修改 BeanFactory 配置 的机会
- 时机:
- BeanDefinition 已经加载完成(
obtainFreshBeanFactory()→loadBeanDefinitions()之后) - Bean 还未实例化
- BeanDefinition 已经加载完成(
- 可以在此做的操作:
- 注册额外的
BeanPostProcessor - 修改某些
BeanDefinition的元信息(scope、lazy-init、属性值等) - 增加特殊的依赖解析规则或容器级别功能
- 注册额外的
# 5. invokeBeanFactoryPostProcessors
提供给开发者的扩展点,可用于 注册或修改 BeanDefinition。BFPP在这一步进行注册, 注册后直接循环调用。
Bean 的 动态装配也是在这一步实现 (@Import / BeanDefinitionRegistry)
invokeBeanFactoryPostProcessors(beanFactory)
│
├─ 如果 beanFactory 是 BeanDefinitionRegistry 类型
│ │
│ ├─ 将传入的 BeanFactoryPostProcessor 拆分
│ │ ├─ BeanDefinitionRegistryPostProcessor → 可以注册/修改 BeanDefinition
│ │ └─ 普通 BeanFactoryPostProcessor → 后处理 BeanDefinition 元信息
│ │
│ ├─ 处理 BeanDefinitionRegistryPostProcessor(PriorityOrdered)
│ │ ├─ 获取容器中所有 PriorityOrdered 类型
│ │ ├─ 排序
│ │ └─ 调用 postProcessBeanDefinitionRegistry()
│ │
│ ├─ 处理 BeanDefinitionRegistryPostProcessor(Ordered)
│ │ ├─ 获取 Ordered 类型
│ │ ├─ 排序
│ │ └─ 调用 postProcessBeanDefinitionRegistry()
│ │
│ ├─ 处理剩余未分类的 BeanDefinitionRegistryPostProcessor
│ │ ├─ 循环获取未处理的 BeanDefinitionRegistryPostProcessor
│ │ ├─ 排序
│ │ └─ 调用 postProcessBeanDefinitionRegistry()
│ │
│ └─ 调用所有 BeanDefinitionRegistryPostProcessor 的 postProcessBeanFactory()
│
├─ 调用普通 BeanFactoryPostProcessor 的 postProcessBeanFactory()
│
└─ 处理容器中注册的所有 BeanFactoryPostProcessor
│
├─ 分类为三类
│ ├─ PriorityOrdered 类型
│ ├─ Ordered 类型
│ └─ 非排序类型
│
├─ 按顺序依次调用 postProcessBeanFactory()
│ ├─ PriorityOrdered → 排序 → 调用
│ ├─ Ordered → 排序 → 调用
│ └─ 非排序 → 调用
│
└─ 清理 BeanFactory 元数据缓存(clearMetadataCache)
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
- 分两类处理:
BeanDefinitionRegistryPostProcessor→ 可以注册/修改 BeanDefinition- 普通
BeanFactoryPostProcessor→ 只修改 BeanDefinition 元信息
- 三类排序优先级:PriorityOrdered → Ordered → 非排序
- 循环检查:保证动态注册的 BeanDefinitionRegistryPostProcessor 也能执行
- 最后清理缓存:确保元数据与 BeanDefinition 保持一致
# 6. registerBeanPostProcessors
提供在 Bean 实例化前后增强 的扩展点,例如 AOP、@Autowired 等。不区分前置 或者 后置增强, 在Bean实例化阶段会遍历beanPostProcessors 列表, 通过调用postProcessBeforeInitialization或者postProcessAfterInitialization执行前置后置增强逻辑。
registerBeanPostProcessors(beanFactory, applicationContext)
│
├─ 获取容器中所有 BeanPostProcessor 名称
│
├─ 计算目标 BeanPostProcessor 数量
│ └─ 添加 BeanPostProcessorChecker(检测提前创建的 Bean)
│
├─ 分类 BeanPostProcessor
│ ├─ PriorityOrdered 类型 → priorityOrderedPostProcessors
│ │ └─ 内部增强器(MergedBeanDefinitionPostProcessor)加入 internalPostProcessors
│ ├─ Ordered 类型 → orderedPostProcessorNames
│ └─ 非排序类型 → nonOrderedPostProcessorNames
│
├─ 注册 PriorityOrdered 类型
│ ├─ 排序
│ └─ 调用 registerBeanPostProcessors
│
├─ 注册 Ordered 类型
│ ├─ 获取 Bean 实例
│ ├─ 内部增强器加入 internalPostProcessors
│ ├─ 排序
│ └─ 调用 registerBeanPostProcessors
│
├─ 注册非排序类型
│ ├─ 获取 Bean 实例
│ ├─ 内部增强器加入 internalPostProcessors
│ └─ 调用 registerBeanPostProcessors
│
├─ 注册内部增强器(MergedBeanDefinitionPostProcessor)
│ ├─ 排序
│ └─ 调用 registerBeanPostProcessors
│
└─ 注册 ApplicationListenerDetector
└─ 自动识别并注册 ApplicationListener
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
- 分类注册:PriorityOrdered → Ordered → 非排序 → 内部增强器
- 内部增强器:通常涉及 AOP、@Autowired、@PostConstruct 等
- BeanPostProcessorChecker:提醒在 BeanPostProcessor 注册完成前就被实例化的 Bean
- ApplicationListenerDetector:自动注册事件监听器
# 7. initMessageSource
作用:为容器提供统一的消息解析机制(Internationalization, i18n),允许 Bean 或应用根据
Locale获取对应的文本、提示信息、异常消息等。
initMessageSource(applicationContext)
│
├─ 1. 检查 BeanFactory 中是否已经注册了 MessageSource
│ ├─ 如果有,直接使用该 MessageSource Bean
│ └─ 如果没有,创建默认的 DelegatingMessageSource
│
├─ 2. 配置 MessageSource
│ ├─ 父级 MessageSource(如果存在父上下文,则可以级联查询消息)
│ ├─ 缓存属性和资源文件路径
│ └─ 设置默认文本处理策略(如找不到 key 时返回 key 本身)
│
└─ 3. 将 MessageSource 设置到 ApplicationContext
└─ 通过 getMessage() / getMessageSourceResolvable() 提供统一调用接口
2
3
4
5
6
7
8
9
10
11
12
13
- 统一消息访问接口
- 所有 Bean 或应用可以通过
applicationContext.getMessage(...)获取消息 - 支持多语言(Locale),可根据用户或系统环境动态解析消息文本
- 所有 Bean 或应用可以通过
- 父子容器支持
- 如果父上下文存在
MessageSource,当前上下文会级联查询父上下文 - 保证不同模块或子容器可以共享消息资源
- 如果父上下文存在
- 默认实现
DelegatingMessageSource:默认消息源,通常查找ResourceBundleMessageSource或ReloadableResourceBundleMessageSource- 如果没有自定义 MessageSource,容器会自动创建默认实现,保证消息解析不为空
- 热加载与刷新
- 如果使用
ReloadableResourceBundleMessageSource,可以在运行时刷新消息资源 - 配合
ContextRefreshedEvent可以实现消息或配置的热加载
- 如果使用
- 使用场景
- 国际化文本显示(如 UI 文本、提示信息)
- 异常消息国际化
- 自定义 Bean 内部提示或日志多语言
# 8. initApplicationEventMulticaster
该方法用于 初始化 Spring 的事件广播器(ApplicationEventMulticaster),是 Spring 事件驱动机制的核心步骤。
作用
创建/获取广播器:为容器准备
ApplicationEventMulticaster,用于事件分发。维护监听器:负责注册和管理所有的
ApplicationListener。事件分发:在事件发布时,调用
multicastEvent(event)通知合适的监听器。
执行时机
在
refresh()流程中,在 BeanPostProcessor 注册之后、普通 Bean 实例化之前确保容器启动后,所有
ApplicationListener已注册到广播器中。
核心逻辑
检查用户是否自定义
ApplicationEventMulticasterBean如果有 → 使用用户自定义实现。
如果没有 → 创建默认
SimpleApplicationEventMulticaster并注册到容器。
遍历所有
ApplicationListenerBean,调用addApplicationListener()注册到广播器。
事件驱动机制(观察者模式)
Spring 的事件驱动设计遵循 典型的观察者模式(Observer Pattern)
- 事件发布方(Publisher)
- 调用
ApplicationEventPublisher.publishEvent(event)→ 委托给广播器。
- 调用
- 事件广播器(Multicaster)
- 保存监听器集合 → 遍历并调用匹配监听器的
onApplicationEvent(event)。
- 保存监听器集合 → 遍历并调用匹配监听器的
- 事件监听器(Listener)
- 通过实现
ApplicationListener<E>或@EventListener处理特定事件。
- 通过实现
- 事件发布方(Publisher)
性能优化
- 早期 Spring:广播器向 所有监听器 分发事件,监听器内部再做类型判断。
- Spring 4.2+:广播器在分发时会筛选,只通知对当前事件类型感兴趣的监听器,避免无效回调,提高性能。
其实并没有这么高大上, 本质上你发布的Spring事件会委托给广播器, 广播器持有所有监听器的引用, 循环匹配罢了, 大致示例如下
// 1. 业务代码:发布事件
public void doSomething() {
ApplicationEvent event = new MyEvent(this);
applicationContext.publishEvent(event); // 发布事件
}
// 2. ApplicationContext 发布事件(和同步一样)
public void publishEvent(ApplicationEvent event) {
this.applicationEventMulticaster.multicastEvent(event);
}
// 3. 广播器:区分同步/异步监听器
public void multicastEvent(ApplicationEvent event) {
List<ApplicationListener> listeners = getApplicationListeners(event);
for (ApplicationListener listener : listeners) {
if (isAsyncListener(listener)) {
// 异步监听器:提交到线程池
taskExecutor.submit(() -> listener.onApplicationEvent(event));
} else {
// 同步监听器:直接调用
listener.onApplicationEvent(event);
}
}
}
// 4. 普通监听器
@Component
public class MySyncListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("【同步】监听到事件: " + event);
}
}
// 5. 异步监听器(用 @Async 标记)
@Component
public class MyAsyncListener implements ApplicationListener<MyEvent> {
@Async
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("【异步】监听到事件: " + event);
}
}
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
# 9. onRefresh
作用:在容器刷新过程中留给子类扩展的钩子方法,用于执行子类特定的初始化逻辑。
onRefresh(applicationContext)
│
├─ 1. 子类可覆盖该方法,实现自定义初始化逻辑
│ ├─ WebApplicationContext:初始化 DispatcherServlet、HandlerMapping、HandlerAdapter 等 MVC 组件
│ ├─ 自定义上下文:可以初始化特定资源或组件
│
├─ 2. 执行前提
│ ├─ BeanFactory 已完成标准单例 Bean 的初始化
│ ├─ ApplicationEventMulticaster 已经可用(但监听器可能尚未注册完全)
│
└─ 3. 常见用途
├─ 初始化框架特定 Bean(如 MVC 组件、消息队列监听器)
├─ 配置扩展 Bean 或插件
└─ 启动某些资源或服务
2
3
4
5
6
7
8
9
10
11
12
13
14
# 10. registerListeners
作用:将容器中所有
ApplicationListener注册到ApplicationEventMulticaster(事件传播器)中,以便发布事件时可以正确触发监听器。
registerListeners(beanFactory, applicationContext)
│
├─ 1. 获取容器中所有 ApplicationListener Bean
│ ├─ 直接实现 ApplicationListener 的 Bean
│ └─ 通过 SmartInitializingSingleton 或其它注册方式添加的监听器
│
├─ 2. 将监听器注册到 ApplicationEventMulticaster
│ └─ multicaster.addApplicationListener(listener)
│
├─ 3. 处理 ApplicationListener 的顺序
│ ├─ 支持 PriorityOrdered / Ordered 接口排序
│ └─ 未排序的放到默认顺序
│
└─ 4. 支持早期事件监听(earlyEvents)
└─ 在容器刷新前发布的事件会缓存在 earlyEvents 中,注册完成后重新广播
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 为什么在
onRefresh之后?- 子容器可能有自己的
ApplicationListener - 父子容器的刷新顺序:先刷新父容器 → 父容器事件发布 → 再刷新子容器 → 子容器事件发布
registerListeners放在onRefresh之后,可以确保所有父子容器的监听器都已注册完成,避免漏掉子容器监听器
- 子容器可能有自己的
- 与 finishRefresh 的关系
finishRefresh会调用ContextRefreshedEvent的广播- 如果监听器未注册,就会错过这个事件
- 所以必须先注册监听器,再发布刷新事件
- 早期事件(earlyEvents)处理
- 在某些情况下,Bean 初始化过程中可能触发事件
- 这些事件会先被缓存(earlyEvents),等监听器注册完成后再统一广播
- 避免事件丢失
- 排序规则
- 支持
PriorityOrdered>Ordered> 默认顺序 - 保证关键监听器先执行(如配置刷新、缓存加载、AOP 初始化等)
- 支持
# 11. finishBeanFactoryInitialization
**重点:**所有非懒加载单例 Bean 都会在该方法中被初始化实例化,也就是说之前注册的 BeanDefinition 会被实例化,同时所有增强方法(BPP、MBDPP、Aware 回调等)也会在这里触发。
finishBeanFactoryInitialization(beanFactory)
│
├─ 1. 初始化 ConversionService
├─ 2. 注册默认的 StringValueResolver(占位符解析)
├─ 3. 初始化 LoadTimeWeaverAware Bean
├─ 4. 清除临时 ClassLoader
├─ 5. 冻结 BeanDefinition 配置
│
└─ 6. 实例化剩余的单例 Bean(preInstantiateSingletons)
│
├─ 遍历所有非抽象、非懒加载、单例 BeanDefinition
│ └─ 对 FactoryBean 特殊处理(&FactoryBeanName 才能获取工厂本身)
│
└─ 调用 getBean(beanName) → doGetBean
│
├─ ① 名称转换(别名解析、FactoryBean 处理)
│
├─ ② getSingleton(beanName, allowEarlyReference) → 三级缓存机制
│ ├─ 一级缓存 singletonObjects(完全初始化单例)
│ ├─ 二级缓存 earlySingletonObjects(提前暴露半成品)
│ └─ 三级缓存 singletonFactories(ObjectFactory,延迟生成早期引用,支持 AOP)
│
├─ ③ 如果缓存未命中 → createBean(beanName, mbd, args) → doCreateBean
│ │
│ createBean(beanName, mbd, args)
│ │
│ ├─ ① 实例化 Bean(createBeanInstance)
│ │ └─ 构造方法 / 工厂方法 / Supplier
│ │
│ ├─ ② MergedBeanDefinitionPostProcessor
│ │ └─ postProcessMergedBeanDefinition()
│ │ (解析 @Autowired/@Value/@Resource 等注解元数据,缓存注入点)
│ │
│ ├─ ③ 提前暴露单例(循环依赖处理)
│ │ └─ addSingletonFactory(beanName, ObjectFactory)
│ │ ├─ 三级缓存 singletonFactories:存 ObjectFactory
│ │ ├─ 清理二级缓存 earlySingletonObjects(保证干净状态)
│ │ └─ 注册 beanName 到 registeredSingletons
│ │
│ ├─ ④ populateBean(依赖注入)
│ │ ├─ 遍历 Bean 属性
│ │ │ ├─ 普通属性注入(通过 BeanDefinition)
│ │ │ ├─ @Autowired / @Resource / @Value 注解依赖
│ │ │ │ └─ 调用 getBean(依赖Bean)
│ │ │ │ ├─ 依赖 Bean 已在一级缓存 → 直接返回
│ │ │ │ ├─ 依赖 Bean 正在创建 → 从三级缓存 / earlySingletonObjects 获取半成品
│ │ │ │ └─ 依赖 Bean 未创建 → 递归 createBean
│ │ └─ 注入完成 → Bean 属性已填充
│ │
│ ├─ ⑤ initializeBean(初始化)
│ │ ├─ Aware 接口回调(BeanNameAware、BeanFactoryAware 等)
│ │ ├─ BeanPostProcessor.postProcessBeforeInitialization()
│ │ ├─ init-method / @PostConstruct
│ │ └─ BeanPostProcessor.postProcessAfterInitialization()
│ │ (典型:AOP 代理生成)
│ │
│ ├─ ⑥ 缓存升级(三级 → 二级 → 一级)
│ │ ├─ 调用 getEarlyBeanReference(beanName) → 获取可能的代理对象
│ │ ├─ 放入二级缓存 earlySingletonObjects(半成品或代理)
│ │ ├─ 放入一级缓存 singletonObjects(完全初始化 Bean)
│ │ ├─ 清理二级缓存 earlySingletonObjects
│ │ └─ 清理三级缓存 singletonFactories
│ │
│ └─ ⑦ 注册 DisposableBean(销毁回调)
│
└─ ④ 返回 Bean(可能来自缓存,也可能是新创建的)
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
- MergedBeanDefinitionPostProcessor
- 是
BeanPostProcessor的子类 - 在 createBean 阶段提前执行,用于解析注解元数据(@Autowired / @Value / @Resource)并缓存注入点信息
- 作用:为 populateBean 时的依赖注入做准备
- 是
- populateBean
- 真正发生依赖注入的阶段
- 注入顺序遵循 BeanDefinition 配置和注解
- 循环依赖时,会从三级缓存 / 二级缓存获取半成品 Bean 注入
- BeanPostProcessor
- 初始化前后触发:
postProcessBeforeInitialization、postProcessAfterInitialization - AOP 代理典型在
postProcessAfterInitialization时生成 - initializeBean 阶段还会调用 Aware 回调和 init-method/@PostConstruct
- 初始化前后触发:
- 循环依赖解决流程(以 A ↔ B 为例)
@Component
class A {
@Autowired
private B b;
}
@Component
class B {
@Autowired
private A a;
}
2
3
4
5
6
7
8
9
10
11
- 流程:
- 容器开始创建 A → 实例化 A → 放入三级缓存 singletonFactories
- populateBean(A) → 发现需要 B → 调用 getBean(B)
- 容器创建 B → 实例化 B → 放入三级缓存 singletonFactories
- populateBean(B) → 发现需要 A → getBean(A)
- A 正在创建 → 从三级缓存拿到 A 的早期引用 → 放入二级缓存
- B 注入 A 的早期引用 → 初始化 B → 放入一级缓存
- 回到 A → 注入 B → 初始化 A → 放入一级缓存
- 注意:
- 早期引用(early reference)可能是代理对象
- 循环依赖只针对 单例 Bean 支持
- FactoryBean 需特殊处理:&FactoryBeanName 获取工厂本身,否则返回 FactoryBean 产物
- 缓存升级顺序
- 三级缓存(ObjectFactory) → 二级缓存(earlySingletonObjects) → 一级缓存(singletonObjects)
- 保证:
- 循环依赖期间可以注入半成品或代理
- 完整 Bean 最终存入一级缓存,二三级缓存清理
- 避免重复创建或覆盖 Bean
- DisposableBean 注册
- 初始化完成后,单例 Bean 会注册销毁回调
- 作用:容器关闭时自动调用 destroy 方法
# 12. finishRefresh
作用:完成 Spring 容器刷新流程,发布
ContextRefreshedEvent,可用于触发依赖容器初始化完成后的事件监听、数据热加载、定时任务启动等。
finishRefresh(applicationContext)
│
├─ 1. 初始化 LifecycleProcessor(生命周期处理器)
│ └─ 管理容器中的 Lifecycle Bean(如 SmartLifecycle),确保启动顺序和依赖
│
├─ 2. 调用 LifecycleProcessor.onRefresh()
│ └─ 启动所有生命周期 Bean(SmartLifecycle 自动按 phase 启动)
│
├─ 3. 发布 ContextRefreshedEvent
│ ├─ 所有注册的 ApplicationListener 会收到事件通知
│ ├─ 可用于:
│ │ ├─ 热加载配置或数据
│ │ ├─ 启动定时任务或消息监听器
│ │ └─ 触发依赖容器完成初始化的自定义逻辑
│
├─ 4. 发布其他事件(可选)
│ └─ ApplicationEventMulticaster 会将事件广播给所有监听器
│
└─ 5. 完成容器刷新
└─ 此时容器中所有非懒加载单例 Bean 已完成实例化、初始化、依赖注入
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- ContextRefreshedEvent
- 事件发布时,容器已经完成:
- Bean 的实例化与初始化
- 循环依赖解决
- BeanPostProcessor 和 AOP 代理生效
- 避免在监听器中再去修改 Bean 定义或创建新的单例 Bean(容易引发异常)
- 事件发布时,容器已经完成:
- LifecycleProcessor
- 管理 SmartLifecycle Bean 的自动启动
- 确保按
phase顺序启动 - 容器刷新后生命周期 Bean 已处于运行状态
- 热加载处理
- 数据或配置热加载逻辑可以放在
ApplicationListener<ContextRefreshedEvent>中 - 可以保证 Bean 已经完全可用,避免空指针或循环依赖问题
- 数据或配置热加载逻辑可以放在
- 异常防护
finishRefresh在发布事件前会捕获异常,防止整个刷新流程中断- 事件监听中出现异常不会影响其他 Bean 的初始化
# Spring 常见问题整理
# 1. Spring 的核心扩展点
Spring 提供了多种扩展点,用于在 Bean 创建和容器初始化阶段增强功能:
| 扩展点 | 作用对象 | 触发时机 | 典型用途 | 备注 |
|---|---|---|---|---|
| BeanFactoryPostProcessor (BFPP) | BeanDefinition | Bean 实例化前 | 修改 BeanDefinition 元信息、注册额外 Bean | 工厂级扩展,不依赖 Bean 实例 |
| MergedBeanDefinitionPostProcessor (BMPP) | Bean + BeanDefinition | Bean 实例化后、初始化前 | 解析注解(如 @Autowired/@Value)、缓存依赖元数据 | BPP 的子类,为 populateBean 提供元数据支持 |
| BeanPostProcessor (BPP) | Bean 实例 | 初始化前后 | 依赖注入、AOP 代理、初始化逻辑增强 | 包含 postProcessBeforeInitialization 和 postProcessAfterInitialization |
| 普通 Bean | Bean 实例 | 容器初始化阶段 | 应用逻辑 | 可被 BFPP/BMPP/BPP 增强 |
⚠️ 特殊 Bean(如 BPP/BFPP)不一定会立即实例化,它们主要提供 增强逻辑。
# 2. 扩展点触发顺序
BFPP 阶段
- 容器完成 BeanDefinition 加载
- 执行所有 BeanFactoryPostProcessor
- 修改 BeanDefinition 或注册额外 Bean
注册 BPP
- 调用
registerBeanPostProcessors - 所有 BeanPostProcessor 被提前注册到容器中
- 包含 BMPP 的实现(如
AutowiredAnnotationBeanPostProcessor)
- 调用
BMPP 阶段
postProcessMergedBeanDefinition被调用- Bean 实例已创建,但属性尚未注入
- 缓存注解元数据,为依赖注入和 AOP 提供信息
普通 Bean 实例化
- 调用
createBean/doCreateBean instantiateBean→ 构造方法 / 工厂方法- 提前暴露单例,支持循环依赖
- 调用
populateBean
- 依赖注入
- 对注解依赖(@Autowired、@Value、@Resource)进行注入
- 循环依赖通过三级缓存解决
initializeBean
- 调用 Aware 接口回调
- BPP 的
postProcessBeforeInitialization - init-method / @PostConstruct
- BPP 的
postProcessAfterInitialization(典型:AOP 代理生成)
需要注意 具体哪个bean调用哪个BPP是由BPP的具体实现决定的
缓存升级
- 三级缓存(ObjectFactory) → 二级缓存(earlySingletonObjects) → 一级缓存(singletonObjects)
- Bean 完全初始化后正式放入一级缓存
注册 DisposableBean
- 销毁回调注册
# 3. 循环依赖处理示意
@Component
class A {
@Autowired
private B b;
}
@Component
class B {
@Autowired
private A a;
}
2
3
4
5
6
7
8
9
10
11
- 容器创建 A → 实例化 A → 放入三级缓存(ObjectFactory)
- A 依赖 B → getBean(B) → 实例化 B → 放入三级缓存
- B 依赖 A → getBean(A) → 从三级缓存获取早期引用
- 完成 B 的 populateBean 和初始化 → 放入一级缓存
- 回到 A → 注入 B → 初始化 → 放入一级缓存
🔑 关键点:
- 提前暴露 Bean 用于解决循环依赖
- BMPP 在 populateBean 之前生效,为依赖注入提供元数据
- BPP 在 initializeBean 阶段生效,AOP 代理生成于
postProcessAfterInitialization
# 4. 注意事项
- BPP 与 BMPP 的提前注册
- 必须在普通 Bean 实例化前注册,否则依赖注入、AOP 无法生效
- 循环依赖
- 仅支持 单例 Bean 的循环依赖
- 原型 Bean 循环依赖会抛出异常
- 早期引用
- 对象在三级缓存中可能是“半成品”
postProcessAfterInitialization可替换为代理对象
- BeanFactoryPostProcessor 的限制
- 只能操作 BeanDefinition 元数据
- 不可操作尚未注册的 Bean 或 Bean 实例
- BMPP 解析元数据
- 缓存依赖信息,保证 populateBean 时可以正确注入
- 解析注解(@Autowired/@Value/@Resource)
- 父子容器与事件监听
registerListeners必须在finishBeanFactoryInitialization/onRefresh之后- 确保父子容器的监听器都能收到
ContextRefreshedEvent
- Lifecycle 与初始化顺序
- SmartLifecycle Bean 按
phase启动 - finishRefresh 阶段发布事件,保证 Bean 完全可用
- SmartLifecycle Bean 按
# 5. 总结
- BFPP:修改 BeanDefinition
- BMPP:Bean 实例化后、初始化前,解析元数据、缓存依赖信息
- BPP:Bean 初始化前后增强(依赖注入、AOP、init 方法)
- 普通 Bean:被容器创建和初始化
- 循环依赖、缓存升级、初始化顺序 是理解 Spring 容器的核心
理解这三类扩展点的触发顺序和作用对象,是分析 Spring IOC 行为、调试依赖注入、AOP 和循环依赖问题的关键。
← 不同IOC的流程解析 DI 详解 →