Read OSS

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

为什么要定义这么多接口?原因有三:

  1. 读写职责分离。 BeanFactoryListableBeanFactory 是只读的,ConfigurableBeanFactory 则新增了写操作。业务代码使用读接口,基础设施代码使用可配置接口。

  2. 可枚举与层级化的正交设计。 ListableBeanFactory 支持枚举所有 Bean,HierarchicalBeanFactory 支持父子工厂链(用于 Web 应用中每个 Servlet 拥有独立子上下文的场景)。二者关注点相互独立、互不干扰。

  3. SPI 与客户端 API 的分离。 BeanDefinitionRegistry 是专门用于注册 Bean 定义的纯 SPI 接口,虽然由 DefaultListableBeanFactory 实现,但有意不纳入 BeanFactory 的客户端接口体系。

模板方法链:从注册表到工厂

实现层的类继承体系与接口金字塔相互映射,由四个关键类构成,每一层都承担特定的职责:

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java#L76

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java#L118

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L121

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java#L132-L133

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()。这个方法协调着一条五阶段的流水线:

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L488-L540

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() 来了解各核心阶段的执行过程:

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L556-L607

阶段一 — createBeanInstance():解析构造器(或工厂方法)并实例化原始对象。此时 Bean 尚未注入任何依赖。

阶段二 — applyMergedBeanDefinitionPostProcessors()MergedBeanDefinitionPostProcessor 的实现类扫描 Bean 类以获取注入元数据。AutowiredAnnotationBeanPostProcessor 在此阶段发现 @Autowired 字段和方法,并将元数据缓存起来供阶段四使用。

阶段三 — 早期单例暴露:若允许循环引用,尚未完成初始化的 Bean 会在第 596 行通过一个 singletonFactory lambda 提前暴露出来,这正是打破循环依赖的关键所在。

阶段四 — populateBean():真正执行依赖注入。此处会调用 InstantiationAwareBeanPostProcessor.postProcessProperties(),触发 AutowiredAnnotationBeanPostProcessor 注入阶段二中发现的依赖。

阶段五 — initializeBean():最终的初始化序列值得单独深入分析。

initializeBean 的初始化仪式

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L1799-L1824

initializeBean() 方法按照固定顺序执行以下步骤:

  1. invokeAwareMethods() — 对实现了相应 Aware 接口的 Bean,依次调用 setBeanName()setBeanClassLoader()setBeanFactory()
  2. applyBeanPostProcessorsBeforeInitialization() — 在初始化回调执行之前,所有已注册的 BeanPostProcessor 都有机会检查或包装该 Bean。
  3. invokeInitMethods() — 先调用 InitializingBean.afterPropertiesSet(),再调用 Bean 定义中声明的自定义初始化方法。
  4. 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 来解决这一问题:

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java#L86-L95

/** 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() 中的解析算法按缓存层级逐级查找:

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java#L208-L237

  1. 查找 singletonObjects(一级缓存)——Bean 已完全就绪。
  2. 查找 earlySingletonObjects(二级缓存)——已从工厂提升的早期引用。
  3. 查找 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 则进一步增加了预测性类型解析和早期代理创建能力,用于处理循环依赖中的代理场景。

排序机制同样至关重要——通过 PriorityOrderedOrdered 接口控制执行顺序。AutowiredAnnotationBeanPostProcessor 等基础设施处理器实现了 PriorityOrdered,以确保在任何业务级处理器之前优先执行。

下一步

至此,我们已完整梳理了整个 IoC 容器的结构:从分离读写与枚举关注点的接口金字塔,到逐层构建 Bean 的模板方法链,再到解析循环依赖的三级缓存,最后是让 Spring 具备高度可扩展性的通用钩子 BeanPostProcessor。在下一篇文章中,我们将视角从单个 Bean 的创建拉升到应用启动全流程:AbstractApplicationContext.refresh()——那个分 13 步将整个 Spring 应用唤醒的核心方法。