作者:太虚野老
目录
说明: 3
自定义 Bean 的特性 4
生命周期回调 4
初始化回调 4
销毁回调 5
默认初始化与销毁方法 6
组合使用多种生命周期机制 7
启动与关闭回调 7
在非 Web 应用中优雅关闭 Spring IoC 容器 9
线程安全与可见性 10
ApplicationContextAware和BeanNameAware 10
其他 Aware 接口 11
附录一:组合使用多种生命周期机制 12
附录二:启动与关闭回调 14
附录三: ApplicationContextAware 和 BeanNameAware测试代码
说明:
1.Spring Framework版本:7.0.8
2.开发框架:Spring boot(版本4.0.5)
3.开发工具:eclipse 2026-03 (4.39.0)
4.jdk版本:25
5.操作系统:debian13
自定义 Bean 的特性
Spring框架提供了许多接口,可用于自定义Bean的特性。本节将这些接口分为以下几组:
生命周期回调
ApplicationContextAware和BeanNameAware
其他Aware接口
生命周期回调
要与容器对Bean生命周期的管理进行交互,您可以实现Spring的InitializingBean和DisposableBean接口。容器会为前者调用afterPropertiesSet()方法,为后者调用destroy()方法,以使bean在初始化时和销毁时执行特定操作。
JSR-250的@PostConstruct和@PreDestroy注解通常被视为现代Spring应用中接收生命周期回调的最佳实践。使用这些注解意味着你的bean不会与Spring特定的接口耦合。如需了解更多详情,请参阅使用@PostConstruct和@PreDestroy。
如果你不想使用JSR-250注解,但仍然希望消除耦合,可以考虑使用init-method和destroy-method 的 Bean 定义元数据。
在内部,Spring框架使用BeanPostProcessor实现来处理它能找到的任何回调接口,并调用相应的方法。如果你需要自定义特性或其他Spring默认不提供的生命周期行为,你可以自己实现一个BeanPostProcessor。更多信息请参见容器扩展点。
除了初始化和销毁回调外,Spring 管理的对象还可以实现 Lifecycle 接口,以便这些对象能够参与由容器自身生命周期驱动的启动和关闭过程。
本节将介绍生命周期回调接口。
初始化回调
org.springframework.beans.factory.InitializingBean接口允许bean在容器为bean设置了所有必要属性后执行初始化工作。InitializingBean接口指定了一个方法:
void afterPropertiesSet() throws Exception;我们建议您不要使用InitializingBean接口,因为它不必要地将代码与Spring耦合在一起。或者,我们建议使用@PostConstruct注解或指定一个POJO初始化方法。在基于 XML 的配置元数据情况下,您可以使用 init-method 属性来指定一个无参数 void 类型方法的名称。使用Java配置时,您可以使用@Bean的initMethod属性。请参阅接收生命周期回调。考虑以下示例:
<bean init-method="init"/>public class ExampleBean { public void init() { // do some initialization work } }上述示例与以下示例(由两个列表组成)的效果几乎完全相同:
<bean/>public class AnotherExampleBean implements InitializingBean { @Override public void afterPropertiesSet() { // do some initialization work } }然而,前两个示例中的第一个并未将代码与Spring耦合。
注意:
请注意,@PostConstruct和初始化方法通常在容器的单例创建锁内执行。只有在从@PostConstruct方法返回后,Bean实例才会被视为完全初始化并准备好发布给其他组件。此类单独的初始化方法仅用于验证配置状态,并可能根据给定的配置准备一些数据结构,但不会进行进一步的外部Bean访问活动。否则,存在初始化死锁的风险。
对于需要触发昂贵的初始化后活动(例如异步数据库准备步骤)的场景,您的Bean应该实现SmartInitializingSingleton.afterSingletonsInstantiated()方法,或者依赖于上下文刷新事件:实现ApplicationListener<ContextRefreshedEvent>接口或声明其等效的注解@EventListener(ContextRefreshedEvent.class)。这些变体是在所有常规单例初始化之后执行的,因此处于任何单例创建锁之外。
或者,您可以实现(Smart)Lifecycle接口,并与容器的整体生命周期管理进行集成,包括自动启动机制、预销毁停止步骤以及潜在的停止/重启回调(见下文)。
销毁回调
实现org.springframework.beans.factory.DisposableBean接口,可以让bean在包含它的容器被销毁时获得一个回调。DisposableBean接口指定了一个方法:
void destroy() throws Exception;我们建议您不要使用DisposableBean回调接口,因为它不必要地将代码与Spring耦合。作为替代方案,我们建议使用@PreDestroy注解或指定一个受bean定义支持的泛型方法。使用基于XML的配置元数据,您可以在<bean/>上使用destroy-method属性。使用Java配置时,您可以使用@Bean的destroyMethod属性。请参阅接收生命周期回调。考虑以下定义:
<bean destroy-method="cleanup"/>public class ExampleBean { public void cleanup() { // 执行一些清理工作(例如释放连接池中的连接) } }上述定义与以下定义几乎具有完全相同的效果:
<bean/>public class AnotherExampleBean implements DisposableBean { @Override public void destroy() { // 执行一些清理工作(例如释放连接池中的连接) } }然而,前两个定义中的第一个并没有将代码与Spring耦合。
请注意,Spring 还支持推断销毁方法,检测公共的 close 或 shutdown 方法。这是 Java 配置类中 @Bean 方法的默认行为,并且会自动匹配 java.lang.AutoCloseable 或 java.io.Closeable 实现,而不会将销毁逻辑与 Spring 耦合。
提示
对于使用