news 2026/4/16 18:34:18

java面试必问11:Spring Bean 生命周期:从实例化到销毁,一篇讲透

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java面试必问11:Spring Bean 生命周期:从实例化到销毁,一篇讲透

Spring Bean 生命周期:从实例化到销毁,一篇讲透

面试官:“说一下 Spring Bean 的生命周期。”
你:“Bean 的生命周期包括:实例化、填充属性、初始化前(BeanPostProcessor)、初始化(afterPropertiesSet/init-method)、初始化后、正常使用、销毁。”
面试官:“那 Aware 接口是在哪个阶段调用的?BeanPostProcessor 和 InitializingBean 的执行顺序是怎样的?”
你:“……”

很多人能背出主要阶段,但一追问细节就乱了。本文从源码角度,把 Bean 从创建到销毁的完整流程讲清楚,并附上代码示例和常见面试追问。


一、Bean 生命周期总览

Spring 容器管理 Bean 的完整生命周期可以分为三大阶段:创建(实例化 → 属性填充 → 初始化)→ 使用 → 销毁。其中初始化前后还穿插着各种 Aware 接口和 BeanPostProcessor 扩展点。

完整流程(按时间顺序):

1. 实例化(构造器/工厂方法) 2. 属性赋值(依赖注入) 3. BeanNameAware.setBeanName() 4. BeanClassLoaderAware.setBeanClassLoader() 5. BeanFactoryAware.setBeanFactory() 6. ApplicationContextAware.setApplicationContext()(若容器是 ApplicationContext) 7. BeanPostProcessor.postProcessBeforeInitialization() 8. InitializingBean.afterPropertiesSet() 9. 自定义 init-method 10. BeanPostProcessor.postProcessAfterInitialization() 11. 使用 Bean 12. DisposableBean.destroy() 13. 自定义 destroy-method

下图直观展示了各阶段顺序:

实例化 → 属性填充 → Aware接口 → 前置处理 → 初始化 → 后置处理 → 使用 → 销毁

二、各阶段详解

1. 实例化(Instantiation)

容器通过构造器工厂方法创建 Bean 的实例。此时 Bean 对象已经存在,但属性尚未赋值(均为默认值或 null)。

  • 默认使用无参构造器,如果类没有无参构造器且未指定构造参数,Spring 会抛出异常。
  • 可以通过@Autowired标注有参构造器,或使用factory-method

2. 填充属性(Populate Properties)

Spring 根据配置(XML 中的<property>、注解@Value@Autowired等)为 Bean 的属性赋值。依赖注入发生在这个阶段。

  • 如果存在循环依赖,Spring 会提前暴露半成品对象(通过三级缓存解决)。
  • 属性赋值完成后,Bean 的状态基本完整(但可能尚未完成全部初始化)。

3. Aware 接口回调

如果 Bean 实现了某个 Aware 接口,Spring 会注入对应的资源。执行顺序固定:

Aware 接口注入的资源
BeanNameAwareBean 在容器中的名称(id/name)
BeanClassLoaderAware加载 Bean 的 ClassLoader
BeanFactoryAware当前的BeanFactory实例
ApplicationContextAware当前的ApplicationContext实例(仅在 ApplicationContext 容器中生效)

注意ApplicationContextAwareBeanFactoryAware之后调用,且要求容器是ApplicationContext类型(若为BeanFactory则不会调用)。

4. BeanPostProcessor 前置处理

BeanPostProcessor接口提供了两个方法:postProcessBeforeInitializationpostProcessAfterInitialization。在初始化方法执行前,Spring 会调用所有注册的BeanPostProcessorpostProcessBeforeInitialization方法。

典型用途:修改 Bean 的属性、生成代理对象、执行自定义检查等。Spring 内部很多功能(如@Autowired解析、AOP 代理创建)都是通过BeanPostProcessor实现的。

5. 初始化(Initialization)

初始化阶段包括两部分:

  • InitializingBean.afterPropertiesSet():如果 Bean 实现了该接口,Spring 会调用此方法。
  • 自定义 init-method:可以通过@Bean(initMethod = "init")或 XML 中的init-method指定一个无参方法,在 afterPropertiesSet 之后执行。

执行顺序afterPropertiesSet()先执行,然后执行自定义 init-method。

6. BeanPostProcessor 后置处理

初始化完成后,Spring 调用所有BeanPostProcessorpostProcessAfterInitialization方法。此时 Bean 已经完全准备好,可以返回给调用方。

AOP 代理的创建通常发生在这个阶段:AbstractAutoProxyCreatorBeanPostProcessor的实现,在postProcessAfterInitialization中判断是否需要为 Bean 生成代理对象。

7. Bean 使用

Bean 已经存在于容器中,可以供其他组件@Autowired或通过getBean()获取,执行业务逻辑。

8. 销毁(Destruction)

当容器关闭时(如ApplicationContext.close()),会销毁所有单例 Bean。销毁阶段包括:

  • DisposableBean.destroy():如果 Bean 实现了该接口,Spring 会调用此方法。
  • 自定义 destroy-method:通过@Bean(destroyMethod = "cleanup")或 XML 中的destroy-method指定,在 DisposableBean 的 destroy 之后执行。

作用域影响:上述生命周期描述适用于单例作用域(singleton)。对于原型作用域(prototype),Spring 只负责创建和初始化,不管理销毁,需要用户自行处理。


三、代码示例:完整演示生命周期

@ComponentpublicclassLifecycleBeanimplementsBeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{privateStringname;publicLifecycleBean(){System.out.println("1. 实例化:构造器");}@AutowiredpublicvoidsetName(@Value("testBean")Stringname){this.name=name;System.out.println("2. 属性填充:setName("+name+")");}@OverridepublicvoidsetBeanName(Stringname){System.out.println("3. BeanNameAware: "+name);}@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{System.out.println("4. BeanFactoryAware");}@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{System.out.println("5. ApplicationContextAware");}@OverridepublicvoidafterPropertiesSet()throwsException{System.out.println("7. InitializingBean.afterPropertiesSet()");}@PostConstruct// JSR-250,等价于 init-method 但更常用publicvoidpostConstruct(){System.out.println("6. @PostConstruct (在 afterPropertiesSet 之前?注意顺序)");// 实际执行顺序:@PostConstruct 在 afterPropertiesSet 之前,但早于自定义 init-method// 为清晰,这里单独标注顺序,实际需看注解处理器优先级。}@Bean(initMethod="customInit")// 配置类中指定publicvoidcustomInit(){System.out.println("8. 自定义 init-method");}@Overridepublicvoiddestroy()throwsException{System.out.println("9. DisposableBean.destroy()");}@PreDestroypublicvoidpreDestroy(){System.out.println("10. @PreDestroy (在 destroy 之前)");}publicvoidcustomDestroy(){System.out.println("11. 自定义 destroy-method");}}

注意:@PostConstruct@PreDestroy是 JSR-250 标准,Spring 支持,执行时机分别在afterPropertiesSet之前和destroy之前。


四、BeanPostProcessor 的使用示例

@ComponentpublicclassCustomBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{if(beaninstanceofLifecycleBean){System.out.println("BeanPostProcessor.before: "+beanName);}returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(beaninstanceofLifecycleBean){System.out.println("BeanPostProcessor.after: "+beanName);}returnbean;}}

执行顺序输出(简化):

1. 实例化 2. 属性填充 3. BeanNameAware 4. BeanFactoryAware 5. ApplicationContextAware BeanPostProcessor.before 6. @PostConstruct 7. afterPropertiesSet 8. 自定义 init-method BeanPostProcessor.after ... 使用 ... BeanPostProcessor.before // 原型Bean每次创建都会经过

五、常见面试追问

Q1:BeanPostProcessorInitializingBean的区别?

  • InitializingBeanBean 自身的初始化回调,只针对当前 Bean。
  • BeanPostProcessor容器级的扩展点,对所有 Bean 生效,可以在初始化前后进行统一增强(如代理、属性修改)。

Q2:AOP 代理在哪个阶段创建?

BeanPostProcessor.postProcessAfterInitialization阶段,具体是AbstractAutoProxyCreator类的实现。因此,如果 Bean 需要被代理,最终返回的是代理对象而非原始对象。

Q3:@PostConstruct@PreDestroyafterPropertiesSetdestroy的先后顺序?

  • @PostConstructafterPropertiesSet之前执行(因为CommonAnnotationBeanPostProcessor处理 JSR-250 注解的优先级高于InitializingBean)。
  • @PreDestroydestroy之前执行。

Q4:原型 Bean 的生命周期有什么不同?

  • 原型 Bean 在每次请求时都会创建新实例,执行实例化 → 属性填充 → 初始化(包括 Aware、PostConstruct、InitializingBean 等),但不会执行销毁阶段(容器不管理原型 Bean 的销毁)。用户需要自行处理资源释放。

Q5:FactoryBeanBeanFactory有什么区别?

  • BeanFactory是 Spring 容器的顶级接口,负责管理 Bean。
  • FactoryBean是一个特殊的 Bean,用于生成复杂对象。当通过&前缀获取时返回 FactoryBean 本身,否则返回其getObject()创建的对象。FactoryBean 的生命周期与普通 Bean 类似,但它的getObject()中创建的对象不由 Spring 管理生命周期(除非声明为 prototype)。

六、生命周期扩展点总结

扩展点时机用途
BeanPostProcessor初始化前后全局增强,如代理、属性注入
InstantiationAwareBeanPostProcessor实例化前后、属性填充前后控制实例化、属性赋值
BeanFactoryAware属性填充后,初始化前获取容器引用
InitializingBean自定义初始化前执行特定初始化逻辑
DisposableBean销毁时执行资源清理
@PostConstruct/@PreDestroy同 InitializingBean / DisposableBean注解方式更简洁
ApplicationListener容器事件发布时监听容器启动、关闭等事件

七、总结

阶段关键动作
实例化调用构造器 / 工厂方法
属性填充依赖注入
Aware 回调注入 BeanName、BeanFactory、ApplicationContext
前置处理BeanPostProcessor.postProcessBeforeInitialization
初始化@PostConstruct → afterPropertiesSet → init-method
后置处理BeanPostProcessor.postProcessAfterInitialization
使用业务调用
销毁@PreDestroy → destroy → destroy-method

一句话记住生命周期构造填充属 Aware,前置初始化后置跑;用完销毁两步走,PreDestroy 和 destroy

理解 Bean 生命周期不仅能让你在面试中对答如流,还能帮助你写出更优雅的扩展组件(如自定义BeanPostProcessor)。希望这篇文章能帮你彻底掌握 Spring Bean 的生命周期,欢迎继续讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 18:32:55

利用Open3D实现相机视锥与3D场景的交互式可视化

1. 为什么需要可视化相机视锥&#xff1f; 在3D重建、位姿估计等计算机视觉任务中&#xff0c;我们经常需要直观地理解相机在三维空间中的位置和朝向。想象一下&#xff0c;你正在用手机拍摄房间的各个角落进行3D建模&#xff0c;如果能实时看到每个拍摄角度对应的"视野范…

作者头像 李华
网站建设 2026/4/16 18:30:48

终极自动化方案:用PyFluent打造智能CFD工作流引擎

终极自动化方案&#xff1a;用PyFluent打造智能CFD工作流引擎 【免费下载链接】pyfluent Pythonic interface to Ansys Fluent 项目地址: https://gitcode.com/gh_mirrors/pyf/pyfluent PyFluent作为Ansys Fluent的Pythonic接口&#xff0c;为流体力学分析领域带来了一场…

作者头像 李华
网站建设 2026/4/16 18:30:35

VUE组件props数据流问题解析:如何避免直接修改props引发的报错

1. 为什么VUE组件中直接修改props会报错&#xff1f; 第一次遇到这个报错时&#xff0c;我正赶着上线一个弹窗功能。控制台突然蹦出的红色警告让我一头雾水&#xff1a;"Avoid mutating a prop directly..."。相信很多VUE新手都踩过这个坑&#xff0c;明明只是想改个…

作者头像 李华
网站建设 2026/4/16 18:29:07

CompressO:释放95%存储空间的免费开源视频压缩神器

CompressO&#xff1a;释放95%存储空间的免费开源视频压缩神器 【免费下载链接】compressO Convert any video/image into a tiny size. 100% free & open-source. Available for Mac, Windows & Linux. 项目地址: https://gitcode.com/gh_mirrors/co/compressO …

作者头像 李华