ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

教程:自定义 Bean 的特性

教程:自定义 Bean 的特性 作者:太虚野老目录说明: 3自定义 Bean 的特性 4生命周期回调 4初始化回调 4销毁回调 5默认初始化与销毁方法 6组合使用多种生命周期机制 7启动与关闭回调 7在非 Web 应用中优雅关闭 Spring IoC 容器 9线程安全与可见性 10ApplicationContextAware和BeanNameAware 10其他 Aware 接口 11附录一:组合使用多种生命周期机制 12附录二:启动与关闭回调 14附录三: ApplicationContextAware 和 BeanNameAware测试代码说明:1.Spring Framework版本:7.0.82.开发框架:Spring boot(版本4.0.5)3.开发工具:eclipse 2026-03 (4.39.0)4.jdk版本:255.操作系统: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()方法,或者依赖于上下文刷新事件:实现ApplicationListenerContextRefreshedEvent接口或声明其等效的注解@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 耦合。提示对于使用
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进