Spring IoC 容器与 Bean 生命周期:从源码到生产实践

深入 Spring IoC 容器内核,剖析 getBean 完整调用链、Bean 生命周期回调时序、循环依赖三级缓存源码实现与六大自定义扩展点设计

如果说「IoC 原理」是认识 Spring 的第一课,那么「容器实现」才是真正拉开普通开发者与资深工程师差距的分水岭。本文从源码视角还原 getBean 的完整调用链、Bean 生命周期回调的精确时序、循环依赖三级缓存的每一步细节,并系统梳理六大自定义扩展点,帮助你在生产环境中精准定位问题、写出可扩展的框架级代码。

前置基础可先阅读 Spring IoC 容器与依赖注入原理深度剖析 与 Spring Boot 核心原理与自动配置。

1. IoC 容器内核:BeanFactory 与 ApplicationContext 体系

1.1 BeanFactory 接口族谱

BeanFactory 是整个 IoC 容器的根接口,定义了对 Bean 的获取、类型查询、是否包含等最基本能力。真正的实现体系远比「一个类」复杂:

BeanFactory(根接口)
 ├── HierarchicalBeanFactory ── 父子容器
 │     └── ConfigurableBeanFactory ── parent / 类加载器 / 类型转换
 │           └── DefaultListableBeanFactory ← 核心实现(beanDefinitionMap、singletonObjects)
 └── ListableBeanFactory ── 按类型/注解列举 Bean
       └── ApplicationContext 体系 ── 继承全部子接口
接口/类核心职责
BeanFactory最基本的 getBean 语义,延迟实例化
ListableBeanFactory枚举 Bean、按注解/类型查询
HierarchicalBeanFactory父子容器,子容器优先查找
AutowireCapableBeanFactory暴露 createBean/autowireBean 给框架集成
DefaultListableBeanFactory默认实现,持有全部 Bean 定义与单例缓存
ApplicationContext完整的企业级容器,具备全部子接口能力

1.2 ApplicationContext 的六大附加能力

ApplicationContext 继承 BeanFactory、ListableBeanFactory 等五个接口,叠加了企业级容器所需的一切:

能力实现接口典型场景
国际化MessageSourceMessageSource.getMessage(code, args, locale)
资源加载ResourcePatternResolverclasspath*: 通配符、@PropertySource
事件发布ApplicationEventPublisherpublishEvent() + @EventListener
环境抽象EnvironmentCapablegetEnvironment() 读取 profile / 属性
AOP 自动织入AutowireCapableBeanFactory@EnableAspectJAutoProxy 自动注册
自动后处理内置多个 BeanPostProcessorCommonAnnotationBeanPostProcessor 等

Spring Boot 中默认的容器实例是 AnnotationConfigApplicationContext(非 Web)或 AnnotationConfigServletWebServerApplicationContext(Web),它们最终都委托给内部的 DefaultListableBeanFactory。

1.3 getBean 完整调用链源码

getBean 是容器最核心的入口,我们沿着调用链看每一步做了什么:

getBean(name)
  └─ doGetBean(name, requiredType, args, false)
        ├─ ① transformedBeanName 转换规范名称(去 &)
        ├─ ② getSingleton(beanName) 先查三级缓存 → 命中即返回
        ├─ ③ 父容器兜底查找
        ├─ ④ getMergedLocalBeanDefinition 合并 BeanDefinition
        ├─ ⑤ 处理 dependsOn 依赖(先实例化依赖 Bean)
        ├─ ⑥ 按作用域分支:
        │     ├─ singleton → getSingleton(name, singletonFactory) ← 核心
        │     │     └─ createBean → doCreateBean(见第 3 节)
        │     ├─ prototype → createBean 直接返回(不进缓存)
        │     └─ request/session → RequestScope/SessionScope
        └─ ⑦ TypeConverter 类型适配 requiredType
// AbstractBeanFactory.java(简化)
protected <T> T doGetBean(...) {
    String beanName = transformedBeanName(name);
    Object sharedInstance = getSingleton(beanName);          // ② 三级缓存
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // 父容器 / 合并定义 / dependsOn / 作用域创建...
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                return createBean(beanName, mbd, args);      // ⑥ 核心创建
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
    }
    return adaptBeanInstance(name, bean, requiredType);      // ⑦ 类型适配
}

理解这条链路,就理解了「先查缓存 → 再创建 → 再适配」的三段式容器行为。

2. BeanDefinition 的注册与合并

2.1 BeanDefinition 的结构

BeanDefinition 是 Bean 的「生产图纸」,容器不直接操作对象,而是先解析出 BeanDefinition:

// BeanDefinition 关键属性
class GenericBeanDefinition {
    String scope = "singleton";        // 作用域
    boolean lazyInit;                  // 是否懒加载
    String factoryBeanName;            // factory-bean(实例工厂)
    String factoryMethodName;          // factory-method
    boolean primary;                   // @Primary 优先注入
    String initMethodName;             // init-method
    String destroyMethodName;          // destroy-method
    String[] dependsOn;                // 显式依赖
    boolean autowireCandidate;         // 是否参与自动装配
    ResolvableType resolvableType;     // 泛型类型
    boolean synthetic;                 // 框架内部生成(AOP、事件监听器)
}

2.2 注册的两个入口

// 入口一:@Component 扫描 → 解析候选组件生成 ScannedGenericBeanDefinition
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
scanner.scan("com.example.service");

// 入口二:@Bean 方法 → ConfigurationClassPostProcessor 在刷新早期解析,
// 生成 BeanDefinition,factoryMethodName 指向配置类方法

3. getBean → doCreateBean:对象创建全链路

createBean 最终落到 AbstractAutowireCapableBeanFactory.createBean 与 doCreateBean。这是整个生命周期的心脏:

3.1 实例化前短路:resolveBeforeInstantiation

// AbstractAutowireCapableBeanFactory.createBean(简化)
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    Object bean = resolveBeforeInstantiation(beanName, mbd); // ① 短路机会
    if (bean != null) {
        return bean;   // 直接返回代理或替换 Bean,跳过后续
    }
    return doCreateBean(beanName, mbd, args);                // ② 正式创建
}

resolveBeforeInstantiation 依次调用所有 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation,并执行 postProcessAfterInitialization。AOP 场景下 AbstractAutoProxyCreator 在这里就为适配器 Bean 创建代理。

3.2 实例化策略:InstantiationStrategy

doCreateBean 通过 createBeanInstance 完成对象实例化,底层使用 InstantiationStrategy:

场景策略说明
无参构造 + 非代理SimpleInstantiationStrategy反射 clazz.getDeclaredConstructor().newInstance()
需要子类代理CglibSubclassingInstantiationStrategy生成子类(@Lookup、@Configuration 类、proxyBeanMethods)
@Bean 工厂方法反射调用工厂方法参数通过 AutowireCandidateResolver 解析
FactoryBean先创建 FactoryBean 自身再 getObject() 产出实际 Bean
// ConstructorResolver 依次尝试:
// ① autowireConstructor(@Autowired 构造器)→ ② 主构造器(Spring 4.3+)→ ③ 默认无参构造
Constructor<?> ctor = resolveAutowiredCandidate(...);

3.3 属性填充:populateBean

// doCreateBean 关键片段(简化)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);  // ① 实例化
    Object bean = instanceWrapper.getWrappedInstance();
    if (mbd.isSingleton()) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); // ② 三级缓存入口
    }
    populateBean(beanName, mbd, instanceWrapper);   // ③ 属性填充(依赖注入发生地)
    Object exposedObject = initializeBean(beanName, bean, mbd);  // ④ 初始化回调
    return exposedObject;
}

populateBean 的注入次序是:InstantiationAwareBeanPostProcessor 属性后处理 → byType/byName 自动装配 → @Autowired/@Value/@Resource 注解注入。@Autowired 由 AutowiredAnnotationBeanPostProcessor.postProcessProperties 完成,它通过 InjectionMetadata 一次性解析类上的注入点。

3.4 初始化:initializeBean

initializeBean 是生命周期回调的集中地,顺序严格固定:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);            // ① Aware(BeanName/ClassLoader/BeanFactory)
    Object wrapped = applyBeanPostProcessorsBeforeInitialization(bean, beanName);  // ② BeforeInit
    invokeInitMethods(beanName, wrapped, mbd);     // ③ InitializingBean + init-method
    return applyBeanPostProcessorsAfterInitialization(wrapped, beanName);          // ④ AfterInit(AOP)
}

陷阱提示:invokeAwareMethods 只处理三个最基础的 Aware;其余如 ApplicationContextAware、ApplicationEventPublisherAware 由 ApplicationContextAwareProcessor(一个内置的 BeanPostProcessor)在「② 初始化前」阶段回调。这也是为什么 @PostConstruct 依赖 ApplicationContextAware 注入的值时要注意时序。

4. 生命周期回调完整时序

4.1 全景时序图

Bean 生命周期(单例,含全部回调):
① InstantiationAwareBPP.postProcessBeforeInstantiation(可短路)
② 构造器 / 工厂方法(createBeanInstance)
③ addSingletonFactory(三级缓存提前暴露)
④ populateBean → InstantiationAwareBPP.postProcessProperties(@Autowired 注入)
⑤ ApplicationContextAwareProcessor(ApplicationContextAware 等)
⑥ BeanPostProcessor.postProcessBeforeInitialization → @PostConstruct
⑦ InitializingBean.afterPropertiesSet()   ⑧ 自定义 init-method
⑨ BeanPostProcessor.postProcessAfterInitialization(AOP 代理)
⑩ SmartInitializingSingleton(全部单例创建完成后)
使用中...
销毁:@PreDestroy → DisposableBean.destroy() → destroy-method

4.2 多个 BeanPostProcessor 的链式顺序

Spring 保证 postProcessBeforeInitialization 和 postProcessAfterInitialization 按 Ordered 顺序执行(order 小的先执行),但前后两个阶段方向相反:

BeanPostProcessororderBefore 阶段After 阶段
ApplicationContextAwareProcessor—注入 Aware—
CommonAnnotationBeanPostProcessorInteger.MAX_VALUE执行 @PostConstruct注册 @PreDestroy
AutowiredAnnotationBeanPostProcessor—解析 @Autowired(此时属性已注入)—
AbstractAutoProxyCreatorOrdered.HIGHEST_PRECEDENCE提前暴露代理判断创建代理(AOP)
@Configuration
public class OrderedProcessors {
    @Bean
    public static BeanPostProcessor firstProcessor() {
        return new MyProcessor();     // 实现 Ordered.getOrder() 返回 0
    }
    @Bean
    public static BeanPostProcessor secondProcessor() {
        return new MyProcessor2();    // getOrder() 返回 10
    }
}
// 执行顺序:order 小的 before 先执行,after 反向:小 order 的 after 后执行

4.3 预实例化收尾:SmartInitializingSingleton

ApplicationContext 默认对所有非懒加载单例预实例化,完成后回调 SmartInitializingSingleton.afterSingletonsInstantiated()——这是「所有业务 Bean 已就绪」的可靠信号,适合做启动预热与配置校验:

@Component
public class CacheWarmer implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        productService.preloadHotProducts();   // 此时可安全依赖任意 Bean
    }
}

5. 循环依赖三级缓存源码深挖

5.1 三级缓存结构

循环依赖解决依赖 DefaultSingletonBeanRegistry 的三级缓存,本质是一个「先给引用,后补完整」的两阶段提交:

singletonObjects          一级:Map<String, Object>         完整 Bean,随时可用
earlySingletonObjects     二级:Map<String, Object>         提前暴露的「原始」引用
singletonFactories       三级:Map<String, ObjectFactory<?>> 可生成提前引用的工厂

5.2 getSingleton:从三级到二级的晋升

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);   // 一级:完整 Bean
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName); // 二级:早期引用
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();  // ③ 调工厂产出
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);        // 晋升:三级 → 二级
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

5.3 为什么需要三级而不是两级

答案在于代理:如果目标 Bean 最终会被 AOP 代理,那么提前暴露的必须是代理对象(否则注入的原始对象与最终代理不一致)。但创建代理需要知道 Bean 是否被 AOP 标记,检测发生在实例化之后。三级缓存的 ObjectFactory 把「决策延后」到被依赖方真正访问的那一刻:

// doCreateBean 实例化后立即调用 addSingletonFactory 放入三级
this.singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

// 工厂的核心:getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);   // 生成提前代理
        }
    }
    return exposedObject;
}

5.4 代理场景的完整时间线

A、B 循环依赖,且 B 需要 AOP 代理:
1. 创建 A → addSingletonFactory(A, factory_A)
2. 填充 A 需要 B → getBean(B) → 创建 B → addSingletonFactory(B, factory_B)
3. 填充 B 需要 A → getSingleton(A):
   一级无 → 二级无 → 三级 factory_A.getObject()
   → getEarlyBeanReference 生成代理 A' → A' 入二级 → B 注入 A'
4. B 初始化完成入一级;回到 A 填充注入 B
5. A initializeBean:postProcessAfterInitialization 发现已提前暴露
   → 若 exposedObject == 原始对象,返回「提前代理 A'」;否则校验一致性
6. A(代理)放入一级

5.5 无法解决的循环依赖场景

场景原因解决
构造器注入循环实例化 A 需要 B,B 实例化需要 A,此时 A 还没进三级缓存@Lazy 注入代理 / 重构
prototype 作用域循环prototype 不缓存、无三级缓存参与禁止相互注入 / 改为单例
@Async 循环异步代理需要提前创建,但 AsyncAnnotationBeanPostProcessor 不属于 SmartInstantiation 族拆分 Bean / 单独配置
@Transactional 自调用并非循环依赖问题,而是自调用不经过代理自注入 / AopContext / 拆分
// Spring Boot 2.6+ 默认禁止循环依赖:启动即报错
// spring.main.allow-circular-references=true 可放开(不推荐,只是给存量系统兜底)

6. 自定义扩展点全景

6.1 六大扩展点对比

扩展点触达时机能做什么典型框架
BeanDefinitionRegistryPostProcessor容器刷新早期注册/修改 BeanDefinitionMyBatis MapperScannerConfigurer
BeanFactoryPostProcessorBeanDefinition 已注册,Bean 未实例化修改 BeanDefinition 属性属性占位符替换
BeanPostProcessor每个 Bean 初始化前后包装/替换 Bean 实例AOP、@Autowired 解析
InstantiationAwareBeanPostProcessor实例化前后短路实例化、拦截属性填充自定义依赖注入
FactoryBean创建时隐藏复杂创建过程MyBatis MapperFactoryBean
ImportBeanDefinitionRegistrar处理 @Import 时编程式注册多个 BeanDefinitionSpring 内部、第三方 starter

6.2 BeanFactoryPostProcessor vs BeanDefinitionRegistryPostProcessor

两者都在容器刷新阶段调用,但后者更早、能注册新定义:

@Component
public class MyRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 阶段一:注册新 BeanDefinition(此时尚无 Bean 被实例化)
        AbstractBeanDefinition bd = BeanDefinitionBuilder
            .genericBeanDefinition(MyService.class).setInitMethodName("init").getBeanDefinition();
        registry.registerBeanDefinition("myService", bd);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 阶段二:修改既有 BeanDefinition 属性
        beanFactory.getBeanDefinition("myService").getPropertyValues().add("timeout", 3000);
    }
}

6.3 InstantiationAwareBeanPostProcessor:AOP 织入窗口

public class CustomInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        if (beanName.equals("specialBean")) {
            return new SpecialBeanProxy();   // 直接替换,跳过后续流程
        }
        return null;                          // null → 走正常流程
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) {
        return !beanName.equals("noAutowired");  // false → 跳过属性填充
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        return pvs;   // 属性填充前自定义处理
    }
}

6.4 FactoryBean:隐藏复杂创建

@Component
public class ComplexClientFactoryBean implements FactoryBean<ComplexClient> {
    @Override
    public ComplexClient getObject() {
        // 复杂构建逻辑:连接池、重试、超时、校验
        return ComplexClient.builder().connectionTimeout(5000).poolSize(32).build();
    }
    @Override
    public Class<?> getObjectType() { return ComplexClient.class; }
    @Override
    public boolean isSingleton() { return true; }
}
// 注入 ComplexClient 即可,容器自动调用 getObject()
// 获取 FactoryBean 本身:getBean("&complexClientFactoryBean")

6.5 SmartLifecycle:启动顺序控制

@Component
public class MessageConsumer implements SmartLifecycle {
    private volatile boolean running = false;

    @Override
    public void start() { running = true; }      // 容器启动阶段:启动 MQ 消费者
    @Override
    public void stop() { running = false; }      // 容器关闭阶段:优雅下线
    @Override
    public boolean isRunning() { return running; }
    @Override
    public int getPhase() { return Integer.MAX_VALUE; }
    // phase 越大越晚启动、越早停止:依赖方用小 phase,被依赖方用大 phase
}

6.6 ImportBeanDefinitionRegistrar

public class MyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
        GenericBeanDefinition bd = new GenericBeanDefinition();
        bd.setBeanClass(Router.class);
        bd.getPropertyValues().add("routes", discoverRoutes(importingClassMetadata));
        registry.registerBeanDefinition("router", bd);   // 编程式注册
    }
}

@Configuration
@Import(MyRegistrar.class)     // 组合注解 @EnableXxx 的惯用实现方式
public class AppConfig {}

7. 生产实践:作用域代理、自注入与常见坑

7.1 作用域代理原理

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 的 Bean 注入到单例 Bean 时,注入的是代理对象,代理在每次调用时委托给当前作用域内的真实实例:

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestContextHolder { ... }

@Service
public class OrderFacade {
    private final RequestContextHolder ctx;   // 注入的是代理
    // 每次调用 ctx 的方法,代理解析当前 HTTP 请求对应的真实实例
}

代理由 Scope 接口的 get/remove + 目标 Bean 类型生成(CGLIB 子类或 JDK 接口代理)。代价:每次方法调用多一次代理转发,且 this 内部自调用仍指向代理,字段访问不会被拦截。

7.2 自引用注入

@Service
public class UserService {
    @Autowired
    private UserService self;                     // 自注入:让方法经过代理

    @Transactional
    public void createUser(User u) { ... }

    public void createUserBatch(List<User> users) {
        users.forEach(u -> self.createUser(u));   // 通过 self 调用才能触发事务代理
    }
}

7.3 常见坑清单

坑现象根因与对策
自调用事务失效this.method() 不生效事务基于代理,必须注入自身代理调用
@PostConstruct 访问代理字段拿到的是 null代理字段未注入,应通过方法注入而非字段访问
懒加载 Bean 提前实例化启动变慢、日志出现非预期初始化@Lazy 的 Bean 被 SmartInitializingSingleton 或启动探针触碰
循环依赖告警启动日志 WARNSpring Boot 2.6+ 默认报错,重构而非放开关
构造器注入两个同类型NoUniqueBeanDefinitionException加 @Primary 或 @Qualifier

8. 总结

主题核心要点
容器体系BeanFactory 是根,ApplicationContext 叠加事件/国际化/AOP
创建链路getBean → getSingleton → createBean → doCreateBean → initializeBean
生命周期实例化 → 属性填充 → Aware → BeforeInit → InitializingBean → AfterInit
三级缓存singletonObjects / earlySingletonObjects / singletonFactories
代理提前暴露getEarlyBeanReference 保证注入的是最终代理
扩展点六大扩展点按容器刷新阶段选择
生产坑自调用、作用域代理、循环依赖、懒加载提前触碰

IoC 容器是 Spring 最精密的机械。掌握 getBean 的调用链、生命周期的精确时序与三级缓存的每一步,你就拥有了诊断大多数 Spring 疑难杂症的底层能力;再配合六大扩展点,就能写出 MyBatis、Seata 这类框架级的集成代码。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java-enterprise」更多文章

  1. 云原生 Java:GraalVM 原生镜像、镜像瘦身与 Serverless
  2. Java 安全与合规:安全编码、数据脱敏与供应链防护
  3. WebFlux 响应式编程实战:Reactor 内核、响应式数据访问与选型