☰
Spring Bean 生命周期源码分析:实例化、初始化、后置处理器与销毁
2026/10/9 13:54:59 网站建设 项目流程
如果这篇文章对你有帮助,欢迎关注我的CSDN账号「来福猿」, 有问题可以在评论区留言,我会一一回复。

一、为什么要深入理解 Bean 生命周期

Spring 容器最核心的能力,就是帮我们管理对象的创建、依赖注入、初始化与销毁。很多开发者平常用@Component、@Autowired时并不会刻意关心背后发生了什么,但一旦接触到 AOP、事务、配置动态刷新、循环依赖或者资源泄漏排查,Bean 生命周期就会成为绕不过去的一道坎。

理解 Bean 生命周期至少有四个实际收益:第一,能看懂BeanPostProcessor为什么可以代理对象,从而理解 AOP 的实现基础;第二,能区分@PostConstruct、InitializingBean和自定义init-method的先后顺序,避免初始化逻辑写在错误的位置;第三,能正确释放数据库连接、线程池、文件句柄等资源,防止内存泄漏;第四,能在面试或源码阅读时,快速定位AbstractAutowireCapableBeanFactory中的关键方法。

本文以 Spring 5.x/6.x 的核心源码AbstractAutowireCapableBeanFactory为主线,把 Bean 生命周期拆成实例化、属性填充、初始化、销毁四个阶段,配合可运行的示例代码逐一分析。

二、Bean 生命周期全景流程

先建立整体印象。一个单例 Bean 从无到有、再到销毁,大致经过下面这条链路:

flowchart TD A[读取 BeanDefinition] --> B[createBeanInstance 实例化] B --> C[populateBean 属性填充] C --> D[initializeBean 初始化] D --> E[放入单例池 使用中] E --> F[容器关闭 close] F --> G[destroy 销毁回调]

其中,initializeBean内部又隐藏了一条更细的顺序链,也是最容易被问到的部分:

flowchart TD A[initializeBean] --> B[invokeAwareMethods 回调 Aware 接口] B --> C[BeanPostProcessor before 前置处理] C --> D[InitializingBean.afterPropertiesSet] D --> E[自定义 init-method] E --> F[BeanPostProcessor after 后置处理] F --> G[Bean 就绪]

下面我们沿着这条主线,逐个阶段看源码。

三、阶段一:Bean 实例化

3.1 createBeanInstance:创建 Bean 的入口

实例化解决的是「调用哪个构造方法或工厂方法把对象创建出来」的问题,这一步还没有做属性注入。核心代码在AbstractAutowireCapableBeanFactory#createBeanInstance中,其决策顺序可以概括为:

  • 如果BeanDefinition提供了Supplier,直接调用Supplier.get()创建实例;
  • 如果配置了工厂方法factoryMethod,通过反射调用该静态或实例工厂方法创建;
  • 如果存在已解析的构造器缓存,直接使用缓存的构造器创建;
  • 否则进入构造器推断determineConstructorsFromBeanPostProcessors,交给SmartInstantiationAwareBeanPostProcessor选择合适的构造器;
  • 仍然无法推断时,回退到默认无参构造方法实例化。

源码主流程可简化为:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { Class<?> beanClass = resolveBeanClass(mbd, beanName); // 1. Supplier 优先 Supplier&lt;?&gt; instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 2. 工厂方法 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 3. 构造器推断 Constructor&lt;?&gt;[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, args); } // 4. 默认无参构造 return instantiateBean(beanName, mbd); }

3.2 实例化前后插手的 PostProcessor

在真正调用构造方法前后,InstantiationAwareBeanPostProcessor提供了两个拦截点:

  • postProcessBeforeInstantiation:在实例化之前调用,如果返回值不为null,Spring 会直接使用这个返回值作为 Bean,跳过默认实例化流程,AOP 代理的提前创建就与此有关;
  • postProcessAfterInstantiation:在实例化完成、属性填充之前调用,返回false可以阻止后续属性填充。

这一阶段只是「把对象造出来」,字段里的@Autowired依赖还没有被注入,下一阶段才处理依赖。

四、阶段二:属性填充

实例化得到的是一个「空壳」对象,接下来populateBean负责把配置文件、注解中的依赖值注入进去:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { // 1. 再次给 InstantiationAwareBeanPostProcessor 拦截机会 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } // 2. 按 AUTOWIRE_BY_NAME / AUTOWIRE_BY_TYPE 自动注入 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || AUTOWIRE_BY_TYPE) { autowireByName(...); autowireByType(...); } // 3. 处理 @Autowired、@Value、@Inject 等注解注入 for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); } // 4. 最终把属性值写入 Bean applyPropertyValues(beanName, mbd, bw, pvs); }

这里有一个关键细节:@Autowired注解并不是由核心 BeanFactory 直接处理的,而是通过AutowiredAnnotationBeanPostProcessor这个InstantiationAwareBeanPostProcessor在postProcessProperties中完成注入。这也是为什么把@Autowired称为「后置处理器驱动的注入机制」。

五、阶段三:初始化

属性注入完成后,对象在业务上已经可以工作,但 Spring 还提供了一整套「初始化钩子」,让用户或框架有机会做进一步的定制。这条链路的入口是initializeBean,需要牢记其内部顺序。

5.1 第一步:Aware 接口回调

invokeAwareMethods会依次回调三个Aware接口:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。如果你的 Bean 实现了这些接口,就能拿到自身名称、类加载器和所属工厂的引用。除此之外的EnvironmentAware、ApplicationContextAware等则由ApplicationContextAwareProcessor等专门的处理器完成回调,原理类似。

5.2 第二步:BeanPostProcessor 前置处理

接下来遍历所有BeanPostProcessor,调用postProcessBeforeInitialization。@PostConstruct注解就是通过InitDestroyAnnotationBeanPostProcessor在此时执行的:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }

5.3 第三步:InitializingBean.afterPropertiesSet

如果 Bean 实现了InitializingBean接口,invokeInitMethods会调用它的afterPropertiesSet()。紧接着,如果BeanDefinition上配置了自定义init-method(XML 中的init-method属性,或注解方式@Bean(initMethod = "...")),也会在此后通过反射执行。

protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) { // 1. InitializingBean 接口回调 if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } // 2. 自定义 init-method String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(bean instanceof InitializingBean && "afterPropertiesSet".equals(initMethodName))) { invokeCustomInitMethod(beanName, bean, mbd); } }

5.4 第四步:BeanPostProcessor 后置处理

初始化方法执行完毕后,Spring 会再次遍历BeanPostProcessor,调用postProcessAfterInitialization。这是整个生命周期中「动手脚」最频繁的位置:AbstractAutoProxyCreator就在这里为 Bean 创建 AOP 代理。所以你最终通过getBean拿到的对象,很可能已经不是最初实例化的那个对象了。

把初始化阶段完整串起来,就是下面这张图:

flowchart LR A[Aware 回调] --> B[BeanPostProcessor before / PostConstruct] B --> C[afterPropertiesSet] C --> D[自定义 init-method] D --> E[BeanPostProcessor after / AOP 代理]

六、后置处理器体系详解

理解了上面的流程,再看后置处理器家族会更清晰。它们虽然名字里都带 PostProcessor,但介入时机完全不同,容易混淆:

处理器类型核心接口介入时机典型用途
BeanFactoryPostProcessorBeanFactoryPostProcessor容器启动阶段,Bean 实例化之前修改 BeanDefinition、属性占位符替换、配置中心刷新
BeanPostProcessorBeanPostProcessor每个 Bean 初始化前后日志、校验、AOP 代理创建
InstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor实例化前后、属性填充前后替代默认构造、注解注入、循环依赖处理
DestructionAwareBeanPostProcessorDestructionAwareBeanPostProcessorBean 销毁之前释放资源、清除缓存、@PreDestroy回调

一个容易背错的顺序是:BeanFactoryPostProcessor操作的是「Bean 的定义」,发生在任何 Bean 实例化之前;而BeanPostProcessor操作的是「Bean 的实例」,发生在每个 Bean 的初始化阶段。两者作用对象不同,不能混为一谈。

七、阶段四:销毁

7.1 destroy-method 的执行顺序

当容器调用close()关闭时,单例 Bean 会依次走销毁流程。其执行顺序与初始化基本对称:先执行@PreDestroy,再执行DisposableBean.destroy(),最后执行自定义destroy-method。

flowchart TD A[容器 close] --> B[DestructionAwareBeanPostProcessor before / PreDestroy] B --> C[DisposableBean.destroy] C --> D[自定义 destroy-method] D --> E[资源释放完成]

7.2 registerDisposableBeanIfNecessary

Bean 是否在容器关闭时被销毁,取决于创建流程末尾的registerDisposableBeanIfNecessary。当 Bean 实现了DisposableBean、配置了destroy-method、或者被DestructionAwareBeanPostProcessor标记为需要销毁时,Spring 会将其封装成DisposableBeanAdapter并注册到容器的disposableBeans缓存中,关闭容器时统一回调。

八、源码主流程串讲:doCreateBean

把上面四个阶段合并起来,就得到了 Spring 创建 Bean 的「总导演」AbstractAutowireCapableBeanFactory#doCreateBean,核心逻辑如下:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { // 1. 实例化:创建空的 Bean 实例 BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); Object bean = instanceWrapper.getWrappedInstance(); // 2. 属性填充:完成依赖注入 populateBean(beanName, mbd, instanceWrapper); // 3. 初始化:Aware 回调、before、init 方法、after Object exposedObject = initializeBean(beanName, bean, mbd); // 4. 注册销毁回调 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; }

而initializeBean又把初始化阶段串了起来:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { // 1. Aware 接口回调 invokeAwareMethods(beanName, bean); // 2. 前置处理,@PostConstruct 在此执行 Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 3. 初始化方法:afterPropertiesSet + 自定义 init-method invokeInitMethods(beanName, wrappedBean, mbd); // 4. 后置处理,AOP 代理在此创建 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; }

记住这条调用链,面试中被问到「请描述 Spring Bean 的生命周期」时,基本就能把每个阶段和对应的源码方法一一对应起来了。

九、完整可运行示例

下面用一个注解方式启动的 Spring 应用,把整个生命周期按顺序打印出来,方便对照验证:

import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; public class BeanLifecycleDemo { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); System.out.println("==== 容器启动完成,开始使用 Bean ===="); UserService userService = context.getBean(UserService.class); userService.sayHello(); context.close(); System.out.println("==== 容器已关闭 ===="); } @Configuration static class AppConfig { @Bean(initMethod = "customInit", destroyMethod = "customDestroy") public UserService userService() { return new UserService(); } @Bean public MyBeanPostProcessor myBeanPostProcessor() { return new MyBeanPostProcessor(); } } static class UserService implements InitializingBean, DisposableBean { public UserService() { System.out.println("1. 构造方法:Bean 实例化"); } public void customInit() { System.out.println("4. 自定义 init-method:customInit()"); } @Override public void afterPropertiesSet() { System.out.println("3. InitializingBean.afterPropertiesSet()"); } public void sayHello() { System.out.println("业务方法:sayHello()"); } public void customDestroy() { System.out.println("7. 自定义 destroy-method:customDestroy()"); } @Override public void destroy() { System.out.println("6. DisposableBean.destroy()"); } } static class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println("2. BeanPostProcessor.postProcessBeforeInitialization()"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println("5. BeanPostProcessor.postProcessAfterInitialization()"); } return bean; } } }

运行后控制台输出如下,顺序与前面的源码分析完全一致:

1. 构造方法:Bean 实例化 2. BeanPostProcessor.postProcessBeforeInitialization() 3. InitializingBean.afterPropertiesSet() 4. 自定义 init-method:customInit() 5. BeanPostProcessor.postProcessAfterInitialization() ==== 容器启动完成,开始使用 Bean ==== 业务方法:sayHello() 6. DisposableBean.destroy() 7. 自定义 destroy-method:customDestroy() ==== 容器已关闭 ====

十、常见面试题与易错点

  • 初始化顺序:构造方法 → 属性注入 →@PostConstruct→afterPropertiesSet→ 自定义init-method,不要记反;@PostConstruct本质上是靠BeanPostProcessor的前置方法执行的。
  • 拿到的 Bean 可能被替换:postProcessAfterInitialization返回的对象会替换原对象,这也是 AOP 代理 Bean 的由来;如果处理器返回null,Spring 会保留原对象。
  • BeanFactoryPostProcessor 与 BeanPostProcessor 的区别:前者改定义、在实例化前执行;后者改实例、在初始化前后执行。
  • 为什么构造器注入能部分避免循环依赖:循环依赖的自动解围依赖「先实例化、再填充」的两段式创建,构造器注入在实例化阶段就要求依赖,因此无法靠三级缓存直接解围。
  • 销毁方法不会自动处理所有资源:只有注册到DisposableBeanAdapter的销毁逻辑才会在close()时执行;prototype作用域的 Bean 通常不由容器负责完整销毁,需要调用方自行管理。

十一、总结

Spring Bean 的生命周期可以概括为「两创建、两加工」:createBeanInstance完成实例化,populateBean完成依赖注入,initializeBean完成初始化回调与后置加工,最后在容器关闭时通过dispose链路完成销毁。整条链路的横切扩展能力都来自不同阶段的PostProcessor,这也是 Spring 框架高度可插拔的根本原因。

建议读者把AbstractAutowireCapableBeanFactory#doCreateBean作为阅读入口,配合本文的示例代码在本地断点调试一遍。把调用栈实际走一次,比单纯背诵顺序要可靠得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询