Spring 深度内核-核心容器与扩展机制-Bean 生命周期全景:从扫描到销毁的完整轨迹

1 阅读27分钟

概述

在上一篇《IoC 设计哲学:容器、BeanDefinition 与配置元信息》中,我们深入剖析了 Spring IoC 容器如何将五花八门的配置元信息——XML、注解、Java Config——统一抽象为 BeanDefinition,并注册到容器内部的“图纸库”DefaultListableBeanFactory.beanDefinitionMap 中。当 XmlBeanDefinitionReaderClassPathBeanDefinitionScanner 将配置元信息转化为一条条 BeanDefinition 之后,Bean 的生命周期便从图纸阶段正式启动。本文将从容器刷新过程中 finishBeanFactoryInitialization 的触发点开始,追踪一个 Bean 从图纸到成品、再到最终销毁的完整轨迹。

如果说 IoC 容器是 Spring 的心脏,那么 Bean 的生命周期就是血液流经全身的完整脉络。每一个由 Spring 管理的 Bean——无论是一个 @Service、一个 @Controller,还是一条数据源连接——都必须经历从定义、创建、装配、初始化到最终销毁的严格旅程。理解这条轨迹上每一个扩展点的执行时机与顺序,不仅是阅读 Spring 源码的基础,更是排查线上事故的利器。本文将以 AbstractAutowireCapableBeanFactory 为核心线索,全景呈现 Bean 生命的每一个细节,并结合源码与真实生产案例,让生命周期从枯燥的概念变为可诊断、可控制的工程能力。

  • 全生命周期阶段:BeanDefinition 注册 → 实例化前拦截 → 实例化 →实例化后拦截 → 属性填充 → Aware 回调 → BeanPostProcessor 前置处理 → 初始化 → BeanPostProcessor 后置处理 → 就绪 → 容器关闭 → 销毁。每个阶段都有严格的顺序与依赖。
  • 核心扩展点InstantiationAwareBeanPostProcessor 可拦截实例化并提前返回代理;BeanPostProcessor 提供初始化前后的通用扩展;InitializingBeanDisposableBean 定义了初始化与销毁的契约。
  • 回调顺序@PostConstruct 先于 InitializingBean.afterPropertiesSet 执行,本质是因为 CommonAnnotationBeanPostProcessorpostProcessBeforeInitialization 中处理 @PostConstruct,而 afterPropertiesSetinvokeInitMethods 中执行。
  • 级联效应:例化前若返回非空代理,属性填充、Aware 回调、初始化全被跳过;属性填充若被 postProcessAfterInstantiation 终止,依赖注入直接失效@PostConstruct 执行时 AOP 代理尚未创建,导致 @Async@Transactional 静默失效。
  • 生产事故根源:大量事故源于对后处理器顺序、代理提前暴露、初始化阻塞等理解的缺失,例如 @PostConstruct 阻塞导致上下文启动超时、prototype Bean 资源未释放导致连接池耗尽等。
  • 作用域影响:singleton Bean 在容器刷新时走完完整生命周期,并由容器负责销毁;prototype Bean 每次获取时经历创建和初始化,但销毁回调不受容器管理,必须手动释放资源。

下面是本文的组织架构图,它描绘了 Bean 生命周期的全貌以及关键的级联效应路径。

flowchart TD
    subgraph 概念建立
        M1[模块1: 生命周期全景概览]
        M2[模块2: 从BeanDefinition到实例化前夕]
    end
    subgraph 机制拆解
        M3[模块3: 实例化前后拦截]
        M4[模块4: 实例化]
        M5[模块5: 属性填充]
        M6[模块6: Aware回调序列]
        M7[模块7: BeanPostProcessor前后置处理]
        M8[模块8: 初始化]
        M9[模块9: 就绪与销毁]
    end
    subgraph 实战升华
        M10[模块10: 生产事故排查专题]
        Demo[Demo 代码示例]
    end
    subgraph 总结与面试
        M11[模块11: 面试高频专题]
        速查表[附录: 调用链速查表]
    end
    M1 --> M2 --> M3 --> M4 --> M5 --> M6 --> M7 --> M8 --> M9
    M9 --> M10 --> Demo
    M10 --> M11 --> 速查表

图表说明

  • 主旨概括:全景图突出了 Bean 从定义注册到销毁的单向流水线,以及一个致命但容易被忽视的短路路径——resolveBeforeInstantiation 提前返回代理,直接跳过属性填充和初始化阶段。
  • 逐层分解:首先容器完成 BeanDefinition 加载;在 finishBeanFactoryInitialization 触发实例化前,Spring 会询问所有 InstantiationAwareBeanPostProcessor 是否提前返回代理;若返回非空则立刻跳到就绪,完全跳过 createBeanInstancepopulateBeaninitializeBean;否则严格按实例化→属性填充→Aware→初始化前后→就绪→销毁执行。
  • 设计原理映射:Spring 采用模板方法模式固定了 doCreateBean 的骨架,并在关键节点插入扩展点。级联效应:一旦 postProcessBeforeInstantiation 返回代理对象,Spring 认为该 Bean 已完全创建,后续依赖注入和初始化回调全部省略,极易造成 Bean 状态残缺。
  • 工程实现与关键结论理解这条不可逆的流水线是诊断 Bean 创建异常的基础。任何在 resolveBeforeInstantiation 中返回自定义代理的行为,都必须自行处理依赖注入;在 @PostConstruct 中调用需要 AOP 代理的方法会失效,因为代理尚未创建。这些细节在生产环境屡次酿成事故。

1. Bean 生命周期的全景概览

AbstractApplicationContext.refresh() 执行至 finishBeanFactoryInitialization(beanFactory) 时,所有非懒加载的 singleton Bean 将被预实例化。这些 Bean 必须严格穿越一条由 Spring 容器编排的、包含 12 个阶段的单向流水线。每个阶段都预置了扩展点或回调插槽,而某些阶段的决策将不可逆地改变下游所有步骤的行为——这种 阶段间耦合效应 正是生产环境中 Bean 状态异常的核心根源。

1.1 十二阶段总览

下表不仅列出了每个阶段的名称和核心动作,更从 输入/输出状态级联影响 两个维度给出了完整的认知坐标——前者回答“这个阶段开始时 Bean 是什么状态,结束后变成了什么状态”,后者回答“这个阶段的决策如何影响下游”。

阶段核心动作扩展点 / 回调接口输入状态输出状态级联影响 / 备注
① 注册BeanDefinition 的加载、合并与缓存BeanFactoryPostProcessor.postProcessBeanFactory原始配置元信息(XML / 注解)合并后的 RootBeanDefinition修改 BeanDefinition 会影响后续所有阶段(第一篇详述)
② 实例化前拦截调用 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation只有 Class 对象,尚无 Bean 实例若返回非空对象,则直接作为最终 Bean;否则继续返回非空 → 跳过 ③~⑧,依赖注入与初始化全部失效
③ 实例化通过构造器或工厂方法创建原始 Java 对象SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructorsBeanClass 已确定,但无实例原始对象实例,所有字段为 null选择的构造器会影响后续注入方式
④ 实例化后拦截判断是否终止属性填充InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation原始对象实例若无终止则进入属性填充,否则跳过返回 false → 跳过 ⑤,@Autowired 全部失效
⑤ 属性填充解析 @Autowired@Value 等并注入依赖AutowiredAnnotationBeanPostProcessor.postProcessProperties原始对象,字段为 null依赖已注入,Bean 的业务引用已就绪属性值的修改将直接影响后续初始化逻辑
⑥ Aware 回调回调 BeanNameAwareBeanClassLoaderAwareBeanFactoryAware这三个 Aware 接口属性填充完成Bean 感知到名称、类加载器、工厂ApplicationContextAware 等不在此处回调,由后续阶段处理
⑦ 前置处理调用 BeanPostProcessor.postProcessBeforeInitialization,完成剩余 Aware 回调并执行 @PostConstructApplicationContextAwareProcessorCommonAnnotationBeanPostProcessorBean 依赖已就绪,但未执行自定义初始化@PostConstruct 执行完毕,Aware 回调全部完成此时 AOP 代理未创建,调用自身带切面的方法将失效
⑧ 初始化调用 InitializingBean.afterPropertiesSet() 和自定义 init-methodInitializingBean<bean init-method="...">已完成前置处理用户自定义初始化逻辑执行完毕依赖外部未就绪 Bean 可能触发 NPE;与⑦的顺序固定
⑨ 后置处理调用 BeanPostProcessor.postProcessAfterInitialization,创建 AOP 代理AbstractAutoProxyCreator初始化完成,原始对象若需要,返回 AOP 代理对象替代原始对象此后容器持有的 Bean 引用可能被代理替换
⑩ 就绪Bean 可供业务代码获取,触发 SmartInitializingSingleton 回调SmartInitializingSingleton.afterSingletonsInstantiated所有单例均已走完 ⑨Bean 完全可用,所有单例就绪可在此安全执行依赖其他 Bean 的启动后检查
⑪ 容器关闭发布 ContextClosedEvent,触发销毁流程无用户扩展点容器正在关闭触发所有 singleton 的销毁逻辑
⑫ 销毁依次执行 @PreDestroyDisposableBean.destroy()destroy-methodDestructionAwareBeanPostProcessor(处理 @PreDestroy)、DisposableBeanBean 仍存在,即将被回收资源释放,Bean 生命周期结束prototype Bean 的销毁回调不自动执行,需手动管理

1.2 Bean 生命周期全景流程图与扩展点解析

以下流程图以 颜色区分节点性质

  • 浅橙色:扩展点节点(内置 BeanPostProcessor 子接口)
  • 浅绿色:回调节点(Aware、InitializingBeanDisposableBean 等)
  • 浅灰色:普通阶段节点
  • 深橙色:级联短路节点(会直接跳过后续大段流程)
  • 红色:级联效应导致的最终异常后果
flowchart TD
    A["① 注册<br/>BeanDefinition"]
    B["② 实例化前拦截<br/>【扩展点】InstantiationAwareBeanPostProcessor<br/>.postProcessBeforeInstantiation"]
    C["③ 实例化<br/>【扩展点】SmartInstantiationAwareBeanPostProcessor<br/>.determineCandidateConstructors"]
    D["④ 实例化后拦截<br/>【扩展点】InstantiationAwareBeanPostProcessor<br/>.postProcessAfterInstantiation"]
    E["⑤ 属性填充<br/>【扩展点】AutowiredAnnotationBeanPostProcessor<br/>.postProcessProperties"]
    F["⑥ Aware 回调<br/>【回调】BeanNameAware / BeanClassLoaderAware<br/>BeanFactoryAware"]
    G["⑦ 前置处理<br/>【扩展点】BeanPostProcessor<br/>.postProcessBeforeInitialization<br/>(含 ApplicationContextAwareProcessor、<br/>CommonAnnotationBeanPostProcessor)"]
    H["⑧ 初始化<br/>【回调】InitializingBean.afterPropertiesSet<br/>+ 自定义 init-method"]
    I["⑨ 后置处理<br/>【扩展点】AbstractAutoProxyCreator<br/>.postProcessAfterInitialization"]
    J["⑩ 就绪<br/>【回调】SmartInitializingSingleton<br/>.afterSingletonsInstantiated"]
    K["⑪ 关闭"]
    L["⑫ 销毁<br/>【回调】@PreDestroy / DisposableBean<br/>/ destroy-method"]

    A --> B
    B -- "返回 null(正常流程)" --> C
    B -- "返回非空代理" --> SHORTCUT["⚡ 短路:跳过 ③~⑨"]
    C --> D
    D -- "返回 false" --> SKIP["跳过 ⑤ 属性填充"]
    D -- "继续" --> E
    E --> F
    SKIP --> F
    F --> G
    G --> H
    H --> I
    I --> J
    J --> K
    K --> L
    SHORTCUT -.->|"级联效应:依赖注入缺失,初始化未执行"| BUG["⚠ 生产事故:字段为 null / 状态不完整"]

    style B fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style C fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style D fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style E fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style G fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style I fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
    style F fill:#dcedc8,stroke:#689f38,stroke-width:2px
    style H fill:#dcedc8,stroke:#689f38,stroke-width:2px
    style J fill:#dcedc8,stroke:#689f38,stroke-width:2px
    style L fill:#dcedc8,stroke:#689f38,stroke-width:2px
    style A fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
    style K fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
    style SHORTCUT fill:#ff9800,stroke:#333,stroke-width:2px,color:#fff
    style BUG fill:#e57373,stroke:#b71c1c,stroke-width:2px,color:#fff
    style SKIP fill:#e0e0e0,stroke:#757575,stroke-width:1px

阶段-扩展点/回调对照表

下表与流程图一一对应,并在 类型 列注明该阶段属于 扩展点 还是 回调,同时补充了典型实现与级联影响。

阶段类型关键接口 / 注解典型实现类级联影响
② 实例化前拦截扩展点InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation自定义处理器返回非空 → 跳过 ③~⑨,依赖注入与初始化全部失效
③ 实例化扩展点SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructorsAutowiredAnnotationBeanPostProcessor指定的构造器将影响后续注入和代理创建
④ 实例化后拦截扩展点InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation自定义处理器返回 false → 跳过 ⑤,@Autowired 等注入全部终止
⑤ 属性填充扩展点InstantiationAwareBeanPostProcessor.postProcessPropertiesAutowiredAnnotationBeanPostProcessor修改 PropertyValues 将改变实际注入值
⑥ Aware 回调回调BeanNameAware, BeanClassLoaderAware, BeanFactoryAware无级联影响
⑦ 前置处理扩展点BeanPostProcessor.postProcessBeforeInitializationApplicationContextAwareProcessor, CommonAnnotationBeanPostProcessor此时 AOP 代理未创建;调用需代理的方法导致注解失效
⑧ 初始化回调InitializingBean.afterPropertiesSet, init-method依赖未就绪 Bean 可能触发 NPE
⑨ 后置处理扩展点BeanPostProcessor.postProcessAfterInitializationAbstractAutoProxyCreator返回代理对象后,原始 Bean 引用被替换
⑩ 就绪回调SmartInitializingSingleton.afterSingletonsInstantiated所有单例就绪,安全执行跨 Bean 操作
⑫ 销毁回调@PreDestroy, DisposableBean.destroy, destroy-methodInitDestroyAnnotationBeanPostProcessorprototype Bean 不自动进入此阶段

级联效应深度解析

上图中共有三条值得警惕的级联路径,它们均由 上游扩展点的早期返回或终止信号 触发,并遵循 模板方法模式的单向不可逆性 向下传递。

路径一:实例化前短路(阶段② → ⑩)

触发机制
AbstractAutowireCapableBeanFactory.createBean() 在执行 doCreateBean() 之前调用 resolveBeforeInstantiation()。该方法遍历所有 InstantiationAwareBeanPostProcessor 并执行 postProcessBeforeInstantiation(beanClass, beanName)。若任一处理器返回非 null 对象,Spring 将直接应用 postProcessAfterInitialization(仅后置处理)并返回该对象,完全绕过 doCreateBean 及其内部的所有阶段(③~⑧)。

被跳过的阶段:实例化、属性填充、Aware 回调、前置处理、初始化。
直接后果:返回的对象没有经历依赖注入,所有 @Autowired@Value 字段均为 null@PostConstructafterPropertiesSet 不会执行,内部状态未初始化。
典型事故:自定义处理器提前返回了一个原始对象或未注入依赖的代理,业务调用时抛出 NullPointerException。案例见模块 10 案例四。

路径二:属性填充终止(阶段④ → ⑥)

触发机制
populateBean() 在执行属性赋值前先调用 postProcessAfterInstantiation()。若返回 falsepopulateBean 立即返回,后续的 postProcessPropertiesapplyPropertyValues 均被跳过。

被跳过的阶段:仅 ⑤ 属性填充。
直接后果:Bean 的依赖字段保持为 null,但 Aware 回调和初始化流程仍会执行。afterPropertiesSet 内若校验依赖将抛出 NPE。
典型事故:配置了自定义 InstantiationAwareBeanPostProcessor 以禁止某些 Bean 的自动注入,但未处理好默认值,导致后续逻辑 NPE。

路径三:AOP 代理创建滞后(阶段⑦ → ⑨ 时序错位)

触发机制
@PostConstruct 方法在 CommonAnnotationBeanPostProcessor.postProcessBeforeInitialization 中被反射调用,属于阶段⑦,而 AOP 代理的创建位于阶段⑨的 AbstractAutoProxyCreator.postProcessAfterInitialization。这意味着在 @PostConstruct 内部,this 引用仍然是原始对象,与容器最终暴露的代理对象不是同一个实例。

直接后果:在 @PostConstruct 中调用自身任何带有 @Async@Transactional@Cacheable 等需要 AOP 代理的方法时,目标方法将在原始对象上直接执行,注解切面完全失效。
典型事故:订单服务在 @PostConstruct 中调用 @Async 数据加载方法,结果同步阻塞启动,且高并发下因未走线程池而超时。案例见模块 10 案例一。


这三条级联路径的共同特征在于:容器按照预设模板执行流程,早期扩展点的特殊返回值会被当作“流程终止信号”,后续步骤不再具有执行机会。理解这一特征,是诊断 Bean 创建异常的核心思维模型。


2. 从 BeanDefinition 到实例化前夕

当所有 BeanDefinition 注册完毕后,容器刷新的关键一步 finishBeanFactoryInitialization 负责触发非懒加载 singleton Bean 的预实例化。这一步最终委托给 DefaultListableBeanFactory.preInstantiateSingletons()

// DefaultListableBeanFactory.preInstantiateSingletons()
public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                // ... 处理 FactoryBean
            } else {
                getBean(beanName); // 触发 Bean 创建
            }
        }
    }
}

getBean 会经过一系列委托,最终进入 AbstractAutowireCapableBeanFactory.createBean()。在 createBean 的最前端,Spring 预留了一个决定性的分支——resolveBeforeInstantiation。不过,这一关键扩展点的详细剖析我们留给模块 3(实例化前后拦截),因为它和 postProcessAfterInstantiation 共同组成了 InstantiationAwareBeanPostProcessor 的两大拦截机制。这里只需记住:在真正走 doCreateBean 之前,容器会询问所有 InstantiationAwareBeanPostProcessor 是否要提前返回代理,一旦返回非空,后续全部流程都将被短路。


3. 实例化前后的拦截机制

在生命周期全景图的②(实例化前拦截)和④(实例化后拦截)两个节点上,Spring 通过 InstantiationAwareBeanPostProcessor 接口赋予了开发者两次极其强大的干预机会:一次在原始对象尚未创建时,可以直接返回一个替代对象并短路全部后续流程;另一次在对象刚刚创建、尚未填充属性时,可以立即终止依赖注入。这两处扩展点虽然隶属于同一个接口,但触发时机截然不同,造成的级联效应也各有侧重。

3.1 InstantiationAwareBeanPostProcessor 接口总览

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    // 实例化前回调:可在 Bean 实例化之前返回一个代理对象
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    // 实例化后回调:在实例化之后、属性填充之前执行,返回 false 则停止属性填充
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    // 属性填充时的回调:用于处理属性值(例如 @Autowired 解析)
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return null;
    }
}

前两个方法分别对应生命周期阶段②和④,正是本章的重点。它们都设计为 default 方法,默认返回 nulltrue,即不做任何拦截。只有子类覆写后,才能改变流程走向。

3.2 实例化前拦截:postProcessBeforeInstantiation

调用入口与短路源码

AbstractAutowireCapableBeanFactory.createBean() 中,首先会调用 resolveBeforeInstantiation,其内部逻辑极为关键:

// AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

解读

  • 只有当 beforeInstantiationResolved 不为 false(即之前未被解析过)时才会进入逻辑。
  • 调用 applyBeanPostProcessorsBeforeInstantiation 遍历所有 InstantiationAwareBeanPostProcessor 并执行 postProcessBeforeInstantiation(beanClass, beanName)
  • 如果任意处理器返回非 null 对象,该对象就被当作最终的 Bean 返回,并且再执行一次 BeanPostProcessor 的后置处理(postProcessAfterInitialization),但完全跳过了 doCreateBean 中的实例化、填充、初始化等步骤。
  • 该行为会被标记到 beforeInstantiationResolved = true,防止重复解析。

createBean 方法中紧接着判断:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    return bean; // 直接返回,跳过 doCreateBean
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);

短路的级联效应

一旦 postProcessBeforeInstantiation 返回非空对象,以下阶段会被全部跳过

  • ③ 实例化 (createBeanInstance)
  • ④ 实例化后拦截 (postProcessAfterInstantiation)
  • ⑤ 属性填充 (populateBean)
  • ⑥ Aware 回调
  • ⑦ 前置处理与 @PostConstruct
  • ⑧ 初始化 (afterPropertiesSet + init-method)

只保留一次后置处理(可能再创建代理),但原始的依赖注入和用户初始化逻辑永远不会执行。这是 Spring 生命周期中影响范围最大的级联效应

在生产中,如果自定义处理器在此处返回了一个未经依赖注入的对象,就会导致 @Autowired 字段全为 null,这正是模块 10 案例四的根因。

3.3 实例化后拦截:postProcessAfterInstantiation

调用入口与终止源码

postProcessAfterInstantiationpopulateBean 的初始阶段被调用,位于所有属性赋值之前:

// AbstractAutowireCapableBeanFactory.populateBean() 片段
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // ...
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return; // 直接返回,跳过后续的属性填充
                }
            }
        }
    }
    // 后续才会处理 @Autowired 和 applyPropertyValues...
}

解读

  • populateBean 内部,首先遍历所有 InstantiationAwareBeanPostProcessor,调用 postProcessAfterInstantiation
  • 一旦任意一个处理器返回 falsepopulateBean 方法立即 return,跳过后面的 postProcessProperties@Autowired 处理)和 applyPropertyValues(显式属性赋值)。
  • populateBean 的提前返回不会影响后续的 Aware、初始化等流程——它们仍然在 initializeBean 中照常执行。

级联效应:可控的依赖注入终止

此处的级联影响相对局部:只有阶段⑤属性填充被跳过,其余阶段⑥~⑨不受影响。这意味着:

  • 字段上的 @Autowired@Value 不会被注入,保留为 null
  • 如果 Bean 实现了 InitializingBean,其 afterPropertiesSet 中若校验这些字段,会直接抛 NullPointerException
  • 可被用作一种“保护策略”:当不希望 Spring 自动注入某些字段时,通过该扩展点显式禁掉。

3.4 两种拦截的对比与定位

对比维度实例化前拦截(阶段②)实例化后拦截(阶段④)
触发方法postProcessBeforeInstantiationpostProcessAfterInstantiation
触发时机Bean 实例化之前Bean 实例化之后,属性填充之前
入参只有 Class<?>beanName,尚无对象已有原始对象实例
返回值含义返回非空 → 短路全过程返回 false → 终止属性填充
跳过的阶段③~⑧ 全部跳过仅跳过⑤
后续流程直接进入 postProcessAfterInitialization继续 Aware、@PostConstruct、初始化等
主要风险返回的对象未注入依赖,状态残缺依赖缺失,但初始化逻辑仍会执行

理解这两者的边界非常重要:实例化前拦截更“暴力”,它会直接阻止 Bean 正常出生;实例化后拦截则是一次“精准手术”,只切断注入通道,让 Bean 以“无依赖”状态继续走完后续流程


4. 实例化:从 Class 到原始对象

在通过所有短路检查后,正常流程进入了 doCreateBean 的第一步:createBeanInstance。此时,容器手中只有一个 BeanDefinition 和确定好的 Class,需要创造一个 Java 对象。

// AbstractAutowireCapableBeanFactory.createBeanInstance()
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    // 1. 工厂方法
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // 2. 构造器选择(SmartInstantiationAwareBeanPostProcessor 可干预)
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    // 3. 默认无参构造
    return instantiateBean(beanName, mbd);
}

扩展点SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 可以返回候选构造器数组,从而干预构造器选择。实例化完成后,Bean 以原始对象的形式存在于 BeanWrapper 中,但所有依赖均为 null,属性填充尚未开始


5. 属性填充:依赖的注入

属性填充是将依赖注入 Bean 的过程(不深入依赖解析细节,仅说明在此阶段发生)。

// AbstractAutowireCapableBeanFactory.populateBean()
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // ... (已处理 postProcessAfterInstantiation,见模块3)
    
    // 自动注入或显式属性赋值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
        // 自动装配
    }
    // postProcessProperties:AutowiredAnnotationBeanPostProcessor 在此处理 @Autowired, @Value
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) return;
            pvs = pvsToUse;
        }
    }
    // 应用属性值
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

AutowiredAnnotationBeanPostProcessor 会在 postProcessProperties 中解析 @Autowired@Value 并注入依赖。属性填充完成后,Bean 的业务依赖已满足(但循环依赖可能彼时还是早期引用,后续篇章详解)。


6. Aware 回调序列

在依赖注入完成之后、初始化正式开始之前,Spring 会让 Bean 感知到容器内的一些基础设施。

// AbstractAutowireCapableBeanFactory.invokeAwareMethods()
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

这三行顺序明确:BeanNameAwareBeanClassLoaderAwareBeanFactoryAware
注意ApplicationContextAwareEnvironmentAware 等更高级的 Aware 回调并不在这里,它们由 ApplicationContextAwareProcessor(一个 BeanPostProcessor)在 postProcessBeforeInitialization 阶段处理。


7. BeanPostProcessor 的前置与后置处理

BeanPostProcessor 是生命周期的核心扩展点,分为前置回调 postProcessBeforeInitialization 和后置回调 postProcessAfterInitialization。它们在 initializeBean 的骨架中执行:

// AbstractAutowireCapableBeanFactory.initializeBean()
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) { ... }

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
  • 前置处理applyBeanPostProcessorsBeforeInitialization 中,ApplicationContextAwareProcessor 完成剩余 Aware 回调,CommonAnnotationBeanPostProcessor 执行 @PostConstruct(order 为 LOWEST_PRECEDENCE)。
  • 后置处理applyBeanPostProcessorsAfterInitialization 中,AbstractAutoProxyCreator 检查并创建 AOP 代理。在此阶段之前,AOP 切面均未织入

8. 初始化:三件套的顺序

初始化阶段有三种回调方式,执行顺序极其严格:

  1. @PostConstruct 注解方法 —— 由 CommonAnnotationBeanPostProcessorpostProcessBeforeInitialization 中触发,属于阶段⑦。
  2. InitializingBean.afterPropertiesSet() —— 在 invokeInitMethods 中直接调用。
  3. 自定义 init-method —— 同样由 invokeInitMethods 反射调用。
// AbstractAutowireCapableBeanFactory.invokeInitMethods()
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        ((InitializingBean) bean).afterPropertiesSet();
    }
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

顺序总结@PostConstructafterPropertiesSet()init-method
级联提醒@PostConstruct 执行时 AOP 代理尚未创建(后置处理在后面),因此异步、事务等注解都会失效。


9. 就绪与销毁

初始化完成后,Bean 进入就绪状态,可供应用使用。另外,所有单例初始化完毕后还会触发 SmartInitializingSingleton.afterSingletonsInstantiated(),非常适合做启动后健康检查。

容器关闭时,Spring 会销毁所有 singleton Bean,销毁顺序:

  1. @PreDestroy —— 由 DestructionAwareBeanPostProcessorInitDestroyAnnotationBeanPostProcessor)处理。
  2. DisposableBean.destroy()
  3. 自定义 destroy-method
// DisposableBeanAdapter.destroy()
public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }
    if (this.invokeDisposableBean) {
        ((DisposableBean) bean).destroy();
    }
    if (this.destroyMethod != null) {
        invokeCustomDestroyMethod(this.destroyMethod);
    }
}

关键结论:prototype Bean 的销毁回调不会自动触发,必须手动管理资源。


10. 生产事故排查专题

10.1 @PostConstruct 中调用 @Async 方法导致异步失效

事故现象:某订单系统在 @PostConstruct 中调用 @Async 预加载方法,却同步执行,阻塞启动。

排查思路:线程名始终为 main,怀疑代理未生效;在 ApplicationRunner 中测试异步正常。

根因分析@PostConstruct 在阶段⑦(postProcessBeforeInitialization)执行,此时 AOP 代理尚未创建(阶段⑨),this 是原始对象,@Async 切面未织入。

解决方案:改用 ApplicationRunner@EventListener(ContextRefreshedEvent.class) 触发异步逻辑。

最佳实践:绝对不在 @PostConstructafterPropertiesSet 中调用依赖 AOP 代理的方法。

10.2 afterPropertiesSet 依赖的 Bean 为 null 导致启动失败

事故现象:启动时 NPE,堆栈指向 afterPropertiesSet,其中访问的 @Autowired 字段为 null。

排查思路:存在循环依赖;检查依赖链发现间接循环。被依赖的 Bean 暴露了早期引用,自身状态可能不完整。

根因分析:循环依赖导致注入的是尚未完成初始化的早期引用,状态残缺。属性填充虽然在 afterPropertiesSet 之前,但循环依赖扰乱了正常顺序。

解决方案:消除循环依赖;使用 @DependsOn;或采用 ObjectProvider 延迟获取。

最佳实践:在初始化回调中只做本 Bean 内部校验,避免依赖未就绪的外部 Bean。

10.3 prototype Bean 实现 DisposableBean 但资源未释放

事故现象:服务运行一段时间后文件句柄耗尽(Too many open files)。

排查思路:prototype Bean 持有文件流,实现了 DisposableBean 并关闭流,但 destroy 从未调用。

根因分析:Spring 对 prototype Bean 只负责创建和初始化,容器不持有其引用,因此不会自动调用销毁回调。

解决方案:调用方手动调用 destroyBean;使用 DestructionAwareBeanPostProcessor;或采用对象池/重构为 singleton。

最佳实践:prototype Bean 应尽量避免持有需显式释放的资源,否则必须构建自定义的资源管理机制。

10.4 InstantiationAwareBeanPostProcessor 提前返回代理导致属性丢失(可选案例)

现象:某 Bean 的所有 @Autowired 字段均为 null。
排查思路:发现 doCreateBean 未被调用,resolveBeforeInstantiation 返回了代理。
根因分析:自定义处理器在 postProcessBeforeInstantiation 返回了非空对象,短路全流程,未注入依赖。
解决方案:在代理内部手动 autowireBean,或改用 postProcessAfterInitialization 创建代理。
最佳实践:谨慎使用短路功能,确保返回的对象具有完整状态。


11. 面试高频专题

(本模块与正文严格隔离,以下为22道经典面试题,每题含标准回答、追问和加分回答)

Q1: 详细描述 Spring Bean 的完整生命周期。

标准回答:12阶段:①注册 → ②实例化前拦截 → ③实例化 → ④实例化后拦截 → ⑤属性填充 → ⑥Aware回调 → ⑦前置处理(@PostConstruct) → ⑧初始化(afterPropertiesSet/init-method) → ⑨后置处理(AOP代理) → ⑩就绪 → ⑪关闭 → ⑫销毁(@PreDestroy/DisposableBean/destroy-method)。
追问ApplicationContextAware 何时调用?(阶段⑦) 短路后会怎样?(跳过③~⑨)
加分回答:源码入口 AbstractAutowireCapableBeanFactory.doCreateBean()

Q2: BeanPostProcessor 和 InitializingBean 的执行顺序?为什么这样设计?

标准回答postProcessBeforeInitialization 在前,InitializingBean 在中间,postProcessAfterInitialization 在后。设计为装饰器模式,允许外部增强包裹内部初始化。
追问:如果 @PostConstructafterPropertiesSet 同时存在呢?
加分回答@PostConstructCommonAnnotationBeanPostProcessor 前置处理中,早于 afterPropertiesSet

Q3: @PostConstruct 和 InitializingBean.afterPropertiesSet 哪个先执行?源码依据?

标准回答@PostConstruct 先执行。源码依据:initializeBeanapplyBeanPostProcessorsBeforeInitializationinvokeInitMethods 之前,CommonAnnotationBeanPostProcessor 在这里处理 @PostConstruct,order 为 LOWEST_PRECEDENCE
追问:如果 afterPropertiesSet 调用了 @Async 方法会怎样?
加分回答:仍然失效,因为 AOP 代理在 postProcessAfterInitialization 创建。

Q4: Bean 初始化过程中有哪些干预扩展点?分别在什么时机?

标准回答:② postProcessBeforeInstantiation 可短路;④ postProcessAfterInstantiation 可终止填充;⑦ postProcessBeforeInitialization 可修改 Bean(含@PostConstruct);⑨ postProcessAfterInitialization 可创建代理。
追问:哪些扩展点会影响其他 Bean?
加分回答depends-on 会影响顺序,SmartInitializingSingleton 可访问所有单例。

Q5: InstantiationAwareBeanPostProcessor 和普通 BeanPostProcessor 的区别?短路点在哪?

标准回答:前者多了三个方法,分别对应实例化前后和属性处理;短路点在 postProcessBeforeInstantiation 返回非空对象。源码见 resolveBeforeInstantiation
追问:短路后 initializeBean 还执行吗?
加分回答:不会,只执行 postProcessAfterInitialization,跳过 invokeInitMethods

Q6: Spring 容器关闭时,Bean 的销毁顺序是怎样的?

标准回答@PreDestroy(由 DestructionAwareBeanPostProcessor) → DisposableBean.destroy → 自定义 destroy-method
追问@PreDestroyDisposableBean 可以同时存在吗?顺序会乱吗?
加分回答:可以,顺序固定。CommonAnnotationBeanPostProcessor 的父类实现 DestructionAwareBeanPostProcessor

Q7: prototype Bean 的生命周期和 singleton 有何不同?销毁回调会生效吗?

标准回答:prototype 只经历创建、填充、初始化,容器不管理销毁。销毁回调不自动调用,需手动 destroyBean
追问:如何批量释放 prototype 资源?
加分回答:自定义 Scope 或注册 DestructionCallback

Q8: 什么是 Aware 接口?常见有哪些?ApplicationContextAware 在哪里处理?

标准回答:让 Bean 感知容器的接口。常见的有 BeanNameAwareBeanFactoryAwareApplicationContextAware。前三者在 invokeAwareMethods (阶段⑥),后者在 ApplicationContextAwareProcessorpostProcessBeforeInitialization (阶段⑦)。
追问:自定义 Aware 需要什么?
加分回答:实现对应 BeanPostProcessor

Q9: 在 @PostConstruct 中调用 @Async 方法会异步吗?为什么?

标准回答:不会,同步执行。根源在于 AOP 代理在阶段⑨创建,@PostConstruct 在阶段⑦。
追问:除了 @Async,还有哪些失效?
加分回答@Transactional@Cacheable 等所有基于 AOP 的注解。

Q10: 如何在不重启的情况下动态修改已创建 Bean 的属性?

标准回答:利用 @RefreshScope(Spring Cloud),或自定义 BeanPostProcessor 返回包装代理,代理内部动态获取配置。
追问:直接替换单例池中的对象有什么风险?
加分回答:并发可见性问题,需要处理同步。

Q11: BeanFactoryPostProcessor 和 BeanPostProcessor 的执行时机区别?

标准回答BeanFactoryPostProcessor 在容器刷新阶段、实例化之前,修改 BeanDefinitionBeanPostProcessor 在实例化、初始化阶段。前者在 invokeBeanFactoryPostProcessors,后者在 registerBeanPostProcessors 之后。
追问:能否在 BeanFactoryPostProcessor 中注册新的 Bean?
加分回答:可以,通过 registry.registerBeanDefinition

Q12: 同时使用 @PostConstruct、InitializingBean、init-method,执行顺序?

标准回答@PostConstructafterPropertiesSetinit-method。源码在 initializeBean 顺序固定。
追问:如果 init-methodafterPropertiesSet 同名怎么办?
加分回答:Spring 会检测并跳过重复调用。

Q13: finishBeanFactoryInitialization 做了什么?

标准回答:预实例化所有非懒加载的 singleton Bean,调用 preInstantiateSingletons,触发 getBean 完成全生命周期。
追问:它前面有哪些重要步骤?
加分回答invokeBeanFactoryPostProcessorsregisterBeanPostProcessors

Q14: 在所有 Bean 初始化完成后执行代码有哪些方式?

标准回答SmartInitializingSingleton.afterSingletonsInstantiatedContextRefreshedEvent 监听器、ApplicationRunner/CommandLineRunner
追问:它们执行的顺序?
加分回答afterSingletonsInstantiatedContextRefreshedEventApplicationRunner

Q15: @DependsOn 在生命周期中如何生效?

标准回答:在 doGetBean 时检查 depends-on,优先递归创建依赖的 Bean。它只控制顺序,不能解决循环依赖。
追问:和 @Order 的区别?
加分回答@Order 主要用于集合注入和切面顺序。

Q16: AOP 代理在哪个阶段创建?为什么选这个时机?

标准回答:阶段⑨ postProcessAfterInitialization。此时 Bean 已完全初始化,代理包装安全;若提前,目标对象状态可能不完整。
追问:循环依赖中的早期引用怎么代理?
加分回答:三级缓存 getEarlyBeanReference 会提前创建代理。

Q17: 什么是早期 Bean 引用?在哪个阶段产生?

标准回答:Bean 在实例化后、填充后,通过 addSingletonFactory 暴露的 ObjectFactory。在实例化后 populateBean 之前添加,用于循环依赖。
追问:为什么构造器注入不能解决循环依赖?
加分回答:因为构造器时需要依赖,但早期引用尚未生成。

Q18: prototype Bean 的 @PostConstruct 和 @PreDestroy 生效吗?

标准回答@PostConstruct 每次 getBean 都执行;@PreDestroy 不自动执行,除非手动 destroyBean
追问:如何让 prototype 自动销毁?
加分回答:自定义 Scope 实现。

Q19 (系统设计题): 设计 Bean 健康检查系统

标准回答:实现 SmartInitializingSingleton,在所有单例就绪后遍历检查;用 ConcurrentHashMap 存储状态;对于不健康 Bean 包装代理返回降级结果。考虑级联依赖,避免检查时触发懒加载。
追问:如何不阻塞启动?
加分回答:异步线程执行检查,代理初始返回 “unknown” 状态。

Q20 (系统设计题): 配置热更新方案设计

标准回答:自定义 Scope + 代理(ScopedProxyMode),监听配置变更,清除 Scope 缓存,重新 getBean。注意旧 Bean 销毁需调用 DisposableBean 释放资源,可结合 DestructionCallback
追问:并发安全怎么保证?
加分回答ReadWriteLock,或 CopyOnWrite 思想。

Q21: doCreateBean 方法的执行流程

标准回答createBeanInstance → 应用 MergedBeanDefinitionPostProcessor → 提前暴露 singletonFactorypopulateBeaninitializeBeaninitializeBean 内含 Aware、前置、初始化、后置。
追问:提前暴露的时机和原因?
加分回答:在 addSingletonFactory 之后,为了循环依赖。

Q22: afterPropertiesSet 执行过长怎么排查和优化?

标准回答:用 jstack 查看主线程阻塞在 invokeInitMethods;将耗时逻辑移到 @EventListener(ContextRefreshedEvent.class) 异步执行;使用 @DependsOn 避免阻塞其他 Bean。
追问:如果必须初始化完才能服务怎么办?
加分回答:利用 ApplicationRunner 或启动时健康检查等待就绪。


12. Demo 代码示例

生命周期顺序演示

@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
    @PostConstruct
    public void postConstruct() { System.out.println("1. @PostConstruct"); }

    @Override
    public void afterPropertiesSet() { System.out.println("2. afterPropertiesSet"); }

    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public void customInit() { System.out.println("3. custom init-method"); }

    @PreDestroy
    public void preDestroy() { System.out.println("4. @PreDestroy"); }

    @Override
    public void destroy() { System.out.println("5. DisposableBean.destroy"); }

    public void customDestroy() { System.out.println("6. custom destroy-method"); }
}

@PostConstruct 调用 @Async 失效与修复

// 失效版本
@Component
public class AsyncInPostConstruct {
    @Async
    public void asyncMethod() { System.out.println(Thread.currentThread().getName()); }

    @PostConstruct
    public void init() { asyncMethod(); } // 同步执行
}

// 修复版本
@Component
public class FixedLoader {
    @Async
    public void asyncMethod() { ... }

    @EventListener(ContextRefreshedEvent.class)
    public void onRefresh() { asyncMethod(); }
}

prototype 资源泄漏与手动销毁

@Component
@Scope("prototype")
public class PrototypeResource implements DisposableBean {
    public void doWork() { }
    @Override
    public void destroy() { System.out.println("释放资源"); }
}

// 调用方手动销毁
@Component
public class User {
    @Autowired private ApplicationContext ctx;

    public void use() {
        PrototypeResource res = ctx.getBean(PrototypeResource.class);
        try { res.doWork(); } finally { ctx.getBeanFactory().destroyBean("prototypeResource", res); }
    }
}

实例化前短路导致属性丢失

@Component
public class ShortcutProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        if (beanClass == VictimBean.class) {
            return new VictimBean(); // 跳过填充,@Autowired 字段为 null
        }
        return null;
    }
}

附录:Bean 生命周期调用链速查表

阶段入口方法扩展点 / 回调典型实现类级联效应
① 注册invokeBeanFactoryPostProcessorsBeanFactoryPostProcessorConfigurationClassPostProcessor修改定义影响全局
② 实例化前拦截resolveBeforeInstantiationInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation自定义返回非空跳过③~⑨
③ 实例化createBeanInstanceSmartInstantiationAwareBeanPostProcessor.determineCandidateConstructorsAutowiredAnnotationBeanPostProcessor选择构造器影响注入
④ 实例化后拦截populateBean 开头postProcessAfterInstantiation自定义返回 false 跳过⑤
⑤ 属性填充populateBeanpostProcessPropertiesAutowiredAnnotationBeanPostProcessor实际注入依赖
⑥ Aware 回调invokeAwareMethodsBeanNameAware--
⑦ 前置处理applyBeanPostProcessorsBeforeInitializationBeanPostProcessor.postProcessBeforeInitializationApplicationContextAwareProcessor, CommonAnnotationBeanPostProcessorAOP 未创建
⑧ 初始化invokeInitMethodsInitializingBean.afterPropertiesSet, init-method-依赖未就绪可能 NPE
⑨ 后置处理applyBeanPostProcessorsAfterInitializationBeanPostProcessor.postProcessAfterInitializationAbstractAutoProxyCreator创建 AOP 代理
⑩ 就绪afterSingletonsInstantiatedSmartInitializingSingleton.afterSingletonsInstantiated-所有单例就绪
⑫ 销毁destroy@PreDestroy, DisposableBean, destroy-methodInitDestroyAnnotationBeanPostProcessorprototype 不自动销毁

延伸阅读

  1. 《Spring 揭秘》王福强 —— Bean 生命周期章节
  2. 《Expert One-on-One J2EE Development without EJB》Rod Johnson —— IoC 容器设计初衷
  3. Spring Framework 5.x 官方文档 “Container Extension Points”
  4. Spring 源码分析系列:《AbstractAutowireCapableBeanFactory 详解》
  5. 《Java 并发编程实战》Brian Goetz —— 与 Bean 生命周期中的可见性、线程安全相关