中山网站建设文化咨询,17网站一起做网店广州,一个微信小程序多少钱,WordPress发送邮件按钮版权声明
本文原创作者#xff1a;谷哥的小弟作者博客地址#xff1a;http://blog.csdn.net/lfdfhl一、概述
DisposableBean 是 Spring 框架中用于定义 Bean 销毁时回调行为的核心接口之一。它提供了一个标准化的钩子方法 destroy()#xff0c;允许 Bean 在容器关闭或作用域…
版权声明
本文原创作者谷哥的小弟作者博客地址http://blog.csdn.net/lfdfhl一、概述
DisposableBean 是 Spring 框架中用于定义 Bean 销毁时回调行为的核心接口之一。它提供了一个标准化的钩子方法 destroy()允许 Bean 在容器关闭或作用域结束前执行资源释放、连接关闭、状态清理等销毁逻辑。
该接口与 InitializingBean 构成 Spring Bean 生命周期的对称机制一个负责初始化一个负责销毁。理解 DisposableBean 的源码实现是掌握 Spring 容器生命周期管理的关键环节。二、接口定义
public interface DisposableBean {/*** 在 Bean 被销毁前由容器调用* 用于释放资源、关闭连接、清理缓存等操作* throws Exception 如果销毁过程出错*/void destroy() throws Exception;
}destroy()当 Bean 生命周期结束时如容器关闭、作用域结束Spring 容器会自动调用此方法。执行时机在 DestructionAwareBeanPostProcessor.postProcessBeforeDestruction() 之后destroy-method 之前。异常处理若销毁失败应抛出 ExceptionSpring 会记录日志但通常不会中断容器关闭流程除非配置严格模式。三、核心执行流程分析
DisposableBean 的调用发生在容器关闭阶段其核心逻辑由 AbstractBeanFactory.destroyBean() 和 DefaultSingletonBeanRegistry.destroySingletons() 协同完成。
3.1 destroyBean() 方法源码位于 AbstractBeanFactory
public void destroyBean(Object bean) {destroyBean(getBeanNameForBeanInstance(bean), bean);
}public void destroyBean(String beanName, Object bean) {DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(bean, beanName);if (bean instanceof DisposableBean) {try {((DisposableBean) bean).destroy();}catch (Throwable ex) {throw new BeanCreationException(Destruction of bean with name beanName failed, ex);}}// 调用配置的 destroy-methodString destroyMethodName getDestroyMethodName(beanName);if (destroyMethodName ! null !(bean instanceof DisposableBean destroy.equals(destroyMethodName))) {invokeCustomDestroyMethod(bean, destroyMethodName);}
}代码解析
postProcessBeforeDestruction先通知所有 DestructionAwareBeanPostProcessor允许在销毁前执行自定义逻辑如解绑监听器instanceof DisposableBean检查 Bean 是否实现了 DisposableBean 接口((DisposableBean) bean).destroy()调用 destroy() 方法invokeCustomDestroyMethod最后调用配置的 destroy-method如 XML 中的 destroy-methodclose。3.2 destroySingletons() 方法源码位于 DefaultSingletonBeanRegistry
public void destroySingletons() {if (logger.isTraceEnabled()) {logger.trace(Destroying singletons in this);}synchronized (this.singletonObjects) {this.singletonsCurrentlyInDestruction true;}// 1. 调用 DestructionAwareBeanPostProcessorString[] disposableBeanNames;synchronized (this.disposableBeans) {disposableBeanNames StringUtils.toStringArray(this.disposableBeans.keySet());}for (int i disposableBeanNames.length - 1; i 0; i--) {destroySingleton(disposableBeanNames[i]);}// 2. 清理所有缓存this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();clearSingletonCache();
}代码解析
this.disposableBeans这是一个 MapString, Object在 Bean 创建时注册记录所有实现了 DisposableBean 或配置了 destroy-method 的单例 Bean逆序销毁从后往前遍历 disposableBeanNames确保依赖关系正确的销毁顺序被依赖的后销毁destroySingleton(String)触发单个 Bean 的销毁流程。四、执行顺序详解
DisposableBean.destroy() 的执行顺序如下
DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()DisposableBean.destroy()配置的 destroy-method如 Bean(destroyMethod close) 或 XML 中的 destroy-method注意如果 destroy-method 方法名恰好是 destroy且 Bean 同时实现了 DisposableBean则不会重复调用。五、与 destroy-method 和 PreDestroy 的对比机制类型执行顺序是否依赖 Spring API示例DestructionAwareBeanPostProcessorSpring 扩展点最早是自定义后处理器PreDestroyJSR-250 注解第二由 CommonAnnotationBeanPostProcessor 触发否标准 Java EE 注解PreDestroy public void cleanup()DisposableBean.destroy()Spring 接口第三是public void destroy()destroy-method配置方法最后否bean destroy-methodclose/
特别说明PreDestroy 实际上是通过 CommonAnnotationBeanPostProcessor 实现的它实现了 DestructionAwareBeanPostProcessor 接口因此其执行早于 DisposableBean.destroy()。六、应用场景
6.1 资源释放
Component
public class DatabaseConnectionPool implements DisposableBean {private ListConnection connections new ArrayList();Overridepublic void destroy() throws Exception {for (Connection conn : connections) {if (conn ! null !conn.isClosed()) {conn.close();}}connections.clear();}
}6.2 线程池关闭
Component
public class TaskExecutor implements DisposableBean {private final ExecutorService executor Executors.newFixedThreadPool(10);Overridepublic void destroy() throws Exception {executor.shutdown();if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {executor.shutdownNow();}}
}6.3 缓存清理
Component
public class LocalCacheService implements DisposableBean {private final MapString, Object cache new ConcurrentHashMap();Overridepublic void destroy() throws Exception {cache.clear();logger.info(Local cache cleared on shutdown);}
}七、注册机制DisposableBeanAdapter
Spring 并不直接持有 DisposableBean 实例而是通过 DisposableBeanAdapter 进行适配和封装。
DisposableBeanAdapter 核心逻辑如下
class DisposableBeanAdapter implements DisposableBean, Runnable {private final Object bean;private final String beanName;private String destroyMethodName;private boolean invokeDisposableBean;private boolean nonPublicAccessAllowed;public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,ListDestructionAwareBeanPostProcessor postProcessors, AccessControlContext acc) {this.bean bean;this.beanName beanName;this.invokeDisposableBean (this.bean instanceof DisposableBean);this.destroyMethodName (beanDefinition ! null ? beanDefinition.getDestroyMethodName() : null);// 如果方法名不是 destroy 或者 Bean 没有实现 DisposableBean则需要调用 destroy-methodif (this.destroyMethodName ! null !(this.invokeDisposableBean destroy.equals(this.destroyMethodName)) !beanDefinition.isExternallyManagedDestroyMethod(this.destroyMethodName)) {this.destroyMethod determineDestroyMethod();}}Overridepublic void destroy() {// 1. 调用 DestructionAwareBeanPostProcessorif (this.postProcessors ! null) {for (DestructionAwareBeanPostProcessor processor : this.postProcessors) {processor.postProcessBeforeDestruction(this.bean, this.beanName);}}// 2. 调用 DisposableBean.destroy()if (this.invokeDisposableBean) {try {((DisposableBean) this.bean).destroy();}catch (Throwable ex) {throw new BeanCreationException(Destruction of bean with name this.beanName failed, ex);}}// 3. 调用 destroy-methodif (this.destroyMethod ! null) {try {invokeCustomDestroyMethod(this.destroyMethod);}catch (Throwable ex) {throw new BeanCreationException(Destruction of bean with name this.beanName failed, ex);}}}
}注意事项DisposableBeanAdapter 封装了完整的销毁逻辑包括 PreDestroy、DisposableBean、destroy-method 的调用顺序。八、实践与注意事项
8.1 建议使用替代方案
尽管 DisposableBean 功能完整但官方更推荐使用 PreDestroy 或 destroy-method原因如下
解耦避免 Bean 与 Spring API 耦合标准性PreDestroy 是 Java 标准注解更具通用性灵活性destroy-method 可配置任意方法名无需实现接口。
8.2 注意事项
幂等性destroy() 方法应设计为幂等防止重复调用导致问题异常处理尽量捕获内部异常避免影响其他 Bean 的销毁线程安全销毁过程可能涉及共享资源需注意并发问题避免阻塞长时间阻塞可能影响容器关闭速度建议设置超时。九、源码设计思想分析
DisposableBean 的设计体现了 Spring 的以下核心思想
生命周期完整性与 InitializingBean 形成“初始化-销毁”闭环可扩展性通过 DestructionAwareBeanPostProcessor 支持扩展适配器模式使用 DisposableBeanAdapter 统一管理多种销毁方式依赖顺序逆序销毁确保依赖关系正确容错机制异常被捕获并记录不影响整体销毁流程。DisposableBean 是 Spring 框架中实现 Bean 销毁回调的重要接口。其核心方法 destroy() 在容器关闭时自动调用适用于资源释放、连接关闭、状态清理等场景。
尽管功能强大但出于解耦和标准化考虑推荐优先使用 PreDestroy 注解。理解 DisposableBean 的执行时机、调用顺序及与 DestructionAwareBeanPostProcessor 的关系有助于深入掌握 Spring Bean 的生命周期管理机制。
小结
destroy() 在容器关闭时调用执行顺序为PreDestroy → destroy() → destroy-method由 DisposableBeanAdapter 封装并协调多种销毁方式所有实现了 DisposableBean 的单例 Bean 被注册到 disposableBeans 缓存中销毁过程逆序执行确保依赖关系正确推荐使用 PreDestroy 替代以降低与 Spring 的耦合。