IoC 容器内部机制:BeanFactory 层次结构与 Bean 创建流水线
前置知识
- ›从使用者角度熟悉 Spring 的 @Bean/@Component
- ›对设计模式(模板方法模式、工厂模式)有基本了解
IoC 容器内部机制:BeanFactory 层次结构与 Bean 创建流水线
每个 Spring 应用的核心都是一个 IoC 容器——负责创建、配置、装配并管理应用中所有对象生命周期的子系统。从外部看,它的使用方式十分简单:调用 getBean() 就能拿到一个对象。但在内部,它是一套构建于极致接口隔离、模板方法模式以及精妙循环依赖缓存机制之上的深度分层架构。本文将完整梳理这套结构。
接口金字塔:读操作、写操作与可枚举操作的分离
Spring 容器通过一套精心设计的接口继承体系来实现关注点的精准分离。位于根部的是 BeanFactory——最基础的客户端接口:
spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java#L123-L156
BeanFactory 提供 getBean()、containsBean()、isSingleton() 等只读操作,这也是大多数业务代码所需要的全部能力。接口层次从此分叉延伸:
classDiagram
class BeanFactory {
<<interface>>
+getBean(String name) Object
+containsBean(String name) boolean
+isSingleton(String name) boolean
}
class ListableBeanFactory {
<<interface>>
+getBeanDefinitionNames() String[]
+getBeansOfType(Class) Map
}
class HierarchicalBeanFactory {
<<interface>>
+getParentBeanFactory() BeanFactory
+containsLocalBean(String) boolean
}
class ConfigurableBeanFactory {
<<interface>>
+addBeanPostProcessor(BeanPostProcessor)
+setParentBeanFactory(BeanFactory)
+registerScope(String, Scope)
}
class AutowireCapableBeanFactory {
<<interface>>
+createBean(Class) Object
+autowireBean(Object)
}
class ConfigurableListableBeanFactory {
<<interface>>
+preInstantiateSingletons()
+getBeanDefinition(String) BeanDefinition
}
class BeanDefinitionRegistry {
<<interface>>
+registerBeanDefinition(String, BeanDefinition)
+removeBeanDefinition(String)
}
BeanFactory <|-- ListableBeanFactory
BeanFactory <|-- HierarchicalBeanFactory
HierarchicalBeanFactory <|-- ConfigurableBeanFactory
ConfigurableBeanFactory <|-- ConfigurableListableBeanFactory
ListableBeanFactory <|-- ConfigurableListableBeanFactory
BeanFactory <|-- AutowireCapableBeanFactory
ConfigurableListableBeanFactory <|.. DefaultListableBeanFactory
BeanDefinitionRegistry <|.. DefaultListableBeanFactory
为什么要定义这么多接口?原因有三:
-
读写职责分离。
BeanFactory和ListableBeanFactory是只读的,ConfigurableBeanFactory则新增了写操作。业务代码使用读接口,基础设施代码使用可配置接口。 -
可枚举与层级化的正交设计。
ListableBeanFactory支持枚举所有 Bean,HierarchicalBeanFactory支持父子工厂链(用于 Web 应用中每个 Servlet 拥有独立子上下文的场景)。二者关注点相互独立、互不干扰。 -
SPI 与客户端 API 的分离。
BeanDefinitionRegistry是专门用于注册 Bean 定义的纯 SPI 接口,虽然由DefaultListableBeanFactory实现,但有意不纳入BeanFactory的客户端接口体系。
模板方法链:从注册表到工厂
实现层的类继承体系与接口金字塔相互映射,由四个关键类构成,每一层都承担特定的职责:
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java#L118
classDiagram
class DefaultSingletonBeanRegistry {
-singletonObjects: Map
-singletonFactories: Map
-earlySingletonObjects: Map
+getSingleton(String) Object
#addSingleton(String, Object)
}
class AbstractBeanFactory {
#getBean(String) Object
#doGetBean(String) Object
#createBean(String, RootBeanDefinition)*
}
class AbstractAutowireCapableBeanFactory {
#createBean(String, RootBeanDefinition) Object
#doCreateBean(String, RootBeanDefinition) Object
#populateBean(String, RootBeanDefinition, BeanWrapper)
#initializeBean(String, Object, RootBeanDefinition) Object
}
class DefaultListableBeanFactory {
-beanDefinitionMap: Map
+preInstantiateSingletons()
+registerBeanDefinition(String, BeanDefinition)
}
DefaultSingletonBeanRegistry <|-- AbstractBeanFactory
AbstractBeanFactory <|-- AbstractAutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory <|-- DefaultListableBeanFactory
每一层职责清晰:
- DefaultSingletonBeanRegistry:管理单例缓存(用于解析循环依赖的三级缓存)。
- AbstractBeanFactory:实现
getBean()以及模板方法createBean(),处理合并后的 Bean 定义、FactoryBean 解引用和 Scope 解析。 - AbstractAutowireCapableBeanFactory:实现
createBean(),即真正的 Bean 创建流水线,包括构造器解析、属性注入和初始化。 - DefaultListableBeanFactory:新增 Bean 定义的存储与枚举能力(
getBeansOfType()),以及单例的预实例化。
Bean 创建流水线:从 createBean() 到可用状态
当你调用 getBean("myService") 时,容器最终会进入 AbstractAutowireCapableBeanFactory.createBean()。这个方法协调着一条五阶段的流水线:
sequenceDiagram
participant Client
participant ABF as AbstractBeanFactory
participant AACBF as AbstractAutowireCapableBeanFactory
participant BPP as BeanPostProcessors
Client->>ABF: getBean("myService")
ABF->>AACBF: createBean(name, mbd, args)
Note over AACBF: Phase 0: resolveBeforeInstantiation
AACBF->>BPP: postProcessBeforeInstantiation()
Note right of BPP: Can short-circuit with proxy
AACBF->>AACBF: doCreateBean(name, mbd, args)
Note over AACBF: Phase 1: createBeanInstance
AACBF->>AACBF: Constructor resolution + instantiation
Note over AACBF: Phase 2: applyMergedBeanDefinitionPostProcessors
AACBF->>BPP: postProcessMergedBeanDefinition()
Note right of BPP: @Autowired metadata caching
Note over AACBF: Phase 3: Early singleton exposure
AACBF->>AACBF: addSingletonFactory() for circular refs
Note over AACBF: Phase 4: populateBean
AACBF->>BPP: postProcessProperties()
Note right of BPP: Actually injects @Autowired fields
Note over AACBF: Phase 5: initializeBean
AACBF->>AACBF: invokeAwareMethods()
AACBF->>BPP: postProcessBeforeInitialization()
AACBF->>AACBF: invokeInitMethods() [afterPropertiesSet]
AACBF->>BPP: postProcessAfterInitialization()
Note right of BPP: AOP proxies created here
AACBF-->>Client: Fully initialized bean
让我们深入 doCreateBean() 来了解各核心阶段的执行过程:
阶段一 — createBeanInstance():解析构造器(或工厂方法)并实例化原始对象。此时 Bean 尚未注入任何依赖。
阶段二 — applyMergedBeanDefinitionPostProcessors():MergedBeanDefinitionPostProcessor 的实现类扫描 Bean 类以获取注入元数据。AutowiredAnnotationBeanPostProcessor 在此阶段发现 @Autowired 字段和方法,并将元数据缓存起来供阶段四使用。
阶段三 — 早期单例暴露:若允许循环引用,尚未完成初始化的 Bean 会在第 596 行通过一个 singletonFactory lambda 提前暴露出来,这正是打破循环依赖的关键所在。
阶段四 — populateBean():真正执行依赖注入。此处会调用 InstantiationAwareBeanPostProcessor.postProcessProperties(),触发 AutowiredAnnotationBeanPostProcessor 注入阶段二中发现的依赖。
阶段五 — initializeBean():最终的初始化序列值得单独深入分析。
initializeBean 的初始化仪式
initializeBean() 方法按照固定顺序执行以下步骤:
invokeAwareMethods()— 对实现了相应Aware接口的 Bean,依次调用setBeanName()、setBeanClassLoader()、setBeanFactory()。applyBeanPostProcessorsBeforeInitialization()— 在初始化回调执行之前,所有已注册的BeanPostProcessor都有机会检查或包装该 Bean。invokeInitMethods()— 先调用InitializingBean.afterPropertiesSet(),再调用 Bean 定义中声明的自定义初始化方法。applyBeanPostProcessorsAfterInitialization()— 这是创建 AOP 代理的关键钩子,@Transactional、@Async等基于代理的特性在此处对原始 Bean 进行包装。
BeanFactory 的 Javadoc(第 69–98 行)按顺序记录了完整的生命周期,是整个框架中最重要的 Javadoc 注释之一:
spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java#L69-L98
循环依赖解析:三级缓存
Spring 最复杂也最鲜为人知的特性之一,是它能够解析单例 Bean 之间的循环依赖。Bean A 依赖 Bean B,Bean B 又依赖 Bean A——若没有特殊处理,这将陷入无限循环。
Spring 通过 DefaultSingletonBeanRegistry 中的三个 Map 来解决这一问题:
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Creation-time registry of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
stateDiagram-v2
[*] --> Creating: getBean("A") called
Creating --> InSingletonFactories: createBeanInstance() done,<br/>addSingletonFactory() called
InSingletonFactories --> InEarlySingletonObjects: Another bean requests "A",<br/>factory.getObject() called
InEarlySingletonObjects --> InSingletonObjects: initializeBean() completes,<br/>addSingleton() called
InSingletonObjects --> [*]: Fully ready
note right of InSingletonFactories
Level 3: ObjectFactory lambda
that may create AOP proxy
end note
note right of InEarlySingletonObjects
Level 2: Raw or proxied reference
before full initialization
end note
note right of InSingletonObjects
Level 1: Fully initialized singleton
end note
getSingleton() 中的解析算法按缓存层级逐级查找:
- 查找
singletonObjects(一级缓存)——Bean 已完全就绪。 - 查找
earlySingletonObjects(二级缓存)——已从工厂提升的早期引用。 - 查找
singletonFactories(三级缓存)——调用工厂,将结果提升至二级缓存并返回早期引用。
三级缓存中的工厂是在 doCreateBean() 阶段三注册的 lambda:() -> getEarlyBeanReference(beanName, mbd, bean)。当涉及 AOP 时,getEarlyBeanReference() 可能返回代理对象而非原始 Bean——这也正是为什么要使用工厂而非直接缓存原始实例的原因。
注意: 循环依赖解析仅适用于单例作用域且使用 setter 注入或字段注入的 Bean。构造器注入产生的循环依赖始终会抛出
BeanCurrentlyInCreationException,因为在构造器需要依赖时,原始对象尚未存在。
BeanPostProcessor:通用扩展钩子
spring-beans/src/main/java/org/springframework/beans/factory/config/BeanPostProcessor.java#L67-L111
BeanPostProcessor 可以说是整个框架中最重要的接口。它只有两个默认方法——postProcessBeforeInitialization() 和 postProcessAfterInitialization()——却支撑起了几乎所有 Spring 特性的实现:
flowchart TD
BPP[BeanPostProcessor]
BPP --> AABPP["AutowiredAnnotationBeanPostProcessor<br/>@Autowired, @Value injection"]
BPP --> CABPP["CommonAnnotationBeanPostProcessor<br/>@PostConstruct, @Resource"]
BPP --> AAPC["AbstractAutoProxyCreator<br/>AOP proxies for @Transactional, @Async, @Cacheable"]
BPP --> ALP["ApplicationListenerDetector<br/>Registers @EventListener methods"]
BPP --> SCBPP["ScheduledAnnotationBeanPostProcessor<br/>@Scheduled methods"]
BPP --> Custom["Your custom BeanPostProcessor"]
该接口还有一套子接口体系:InstantiationAwareBeanPostProcessor 在实例化之前提供钩子(供 AOP 使用),SmartInstantiationAwareBeanPostProcessor 则进一步增加了预测性类型解析和早期代理创建能力,用于处理循环依赖中的代理场景。
排序机制同样至关重要——通过 PriorityOrdered 和 Ordered 接口控制执行顺序。AutowiredAnnotationBeanPostProcessor 等基础设施处理器实现了 PriorityOrdered,以确保在任何业务级处理器之前优先执行。
下一步
至此,我们已完整梳理了整个 IoC 容器的结构:从分离读写与枚举关注点的接口金字塔,到逐层构建 Bean 的模板方法链,再到解析循环依赖的三级缓存,最后是让 Spring 具备高度可扩展性的通用钩子 BeanPostProcessor。在下一篇文章中,我们将视角从单个 Bean 的创建拉升到应用启动全流程:AbstractApplicationContext.refresh()——那个分 13 步将整个 Spring 应用唤醒的核心方法。