Spring DisposableBean 源码详解(详细注释版)
1. DisposableBean接口源码
/*
* DisposableBean接口是Spring框架中用于Bean销毁的回调接口
* 当Bean实现了这个接口,Spring容器在关闭时会调用destroy()方法
* 这为Bean提供了在销毁前执行清理工作的机会
*
* 注意:官方推荐使用@PreDestroy注解或destroy-method配置而不是实现此接口
* 因为实现接口会将代码与Spring框架耦合
*/
package org.springframework.beans.factory;
/**
* 在BeanFactory销毁Bean时,需要执行清理工作的Bean实现的接口
*
* 这个接口的主要用途:
* 1. 允许Bean在被销毁前执行清理逻辑
* 2. 提供一种标准的方式来执行销毁操作
* 3. 确保在Bean被回收前完成必要的清理工作
*
* 实现此接口的典型场景:
* - 关闭数据库连接
* - 停止后台线程
* - 释放文件句柄
* - 清理缓存数据
* - 关闭网络连接等
*
* 注意事项:
* - destroy()方法在容器关闭时被调用
* - 如果清理失败,应该记录日志而不是抛出异常
* - 避免在此方法中执行耗时操作,影响应用关闭速度
*/
public interface DisposableBean {
/**
* 在BeanFactory销毁Bean时调用
*
* 这个方法在以下情况下被调用:
* 1. ApplicationContext关闭时
* 2. BeanFactory关闭时
* 3. Web应用停止时
* 4. 手动调用destroy()方法时
*
* 执行时机:
* 应用关闭 -> ApplicationContext关闭 -> BeanFactory销毁Bean ->
* destroy()方法调用 -> Bean被垃圾回收
*
* @throws Exception 如果销毁过程中发生错误
*
* 使用建议:
* - 在此方法中执行必要的清理操作
* - 避免抛出异常,应该记录日志并继续执行
* - 确保清理操作是幂等的(可以多次调用)
* - 避免在此方法中执行复杂的业务逻辑
*/
void destroy() throws Exception;
}
2. AbstractAutowireCapableBeanFactory中DisposableBean的处理
/*
* AbstractAutowireCapableBeanFactory中DisposableBean的注册和调用
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 注册DisposableBean回调
* 在Bean创建完成后调用,注册销毁回调
*
* @param beanName Bean名称
* @param bean Bean实例
* @param mbd 合并的Bean定义
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 单例Bean注册DisposableBean适配器
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, acc));
}
else {
// 其他作用域Bean注册销毁回调
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, acc));
}
}
}
/**
* 判断Bean是否需要销毁
*
* @param bean Bean实例
* @param mbd 合并的Bean定义
* @return 如果需要销毁返回true
*/
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean != null &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
/**
* 销毁单例Bean
* 在容器关闭时调用
*/
@Override
public void destroySingletons() {
super.destroySingletons();
// 销毁所有注册的DisposableBean
this.disposableBeans.destroySingletons();
}
}
/**
* DisposableBean注册表
* 管理所有需要销毁的Bean
*/
@SuppressWarnings("serial")
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
3. DisposableBeanAdapter核心实现
/*
* DisposableBeanAdapter是DisposableBean的适配器实现
* 负责统一处理DisposableBean接口、自定义销毁方法和@PreDestroy注解
*/
class DisposableBeanAdapter implements DisposableBean, BeanPostProcessor {
// 要销毁的Bean实例
private final Object bean;
// Bean名称
private final String beanName;
// 自定义销毁方法名称
private String destroyMethodName;
// 自定义销毁方法
private transient Method destroyMethod;
// 销毁方法是否为非公共方法
private final boolean invokeDisposableBean;
// 安全管理器上下文
private final AccessControlContext acc;
// DestructionAwareBeanPostProcessor列表
private transient DestructionAwareBeanPostProcessor[] postProcessors;
/**
* 构造方法
*
* @param bean Bean实例
* @param beanName Bean名称
* @param mbd Bean定义
* @param acc 安全上下文
*/
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition mbd,
@Nullable AccessControlContext acc) {
this.bean = bean;
this.beanName = beanName;
// 检查是否实现了DisposableBean接口
this.invokeDisposableBean = (bean instanceof DisposableBean);
// 获取自定义销毁方法
inferDestroyMethodIfNecessary(bean, mbd);
// 设置安全上下文
this.acc = acc;
// 获取DestructionAwareBeanPostProcessor
this.postProcessors = filterPostProcessors(mbd);
}
/**
* 推断销毁方法
*
* @param bean Bean实例
* @param mbd Bean定义
*/
private void inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition mbd) {
// 获取销毁方法名称
String destroyMethodName = mbd.getDestroyMethodName();
if (destroyMethodName == null) {
// 如果没有显式指定,检查是否存在close或shutdown方法
destroyMethodName = inferDestroyMethod(bean);
}
if (destroyMethodName != null &&
!(invokeDisposableBean && "destroy".equals(destroyMethodName))) {
this.destroyMethodName = destroyMethodName;
// 查找销毁方法
this.destroyMethod = determineDestroyMethod(destroyMethodName);
}
}
/**
* 推断销毁方法名称
*
* @param bean Bean实例
* @return 销毁方法名称
*/
@Nullable
private String inferDestroyMethod(Object bean) {
// 检查是否存在close方法
if (ClassUtils.hasMethod(bean.getClass(), "close")) {
return "close";
}
// 检查是否存在shutdown方法
if (ClassUtils.hasMethod(bean.getClass(), "shutdown")) {
return "shutdown";
}
return null;
}
/**
* 确定销毁方法
*
* @param destroyMethodName 销毁方法名称
* @return 销毁方法
*/
@Nullable
private Method determineDestroyMethod(@Nullable String destroyMethodName) {
try {
if (destroyMethodName != null) {
// 查找公共方法
Method destroyMethod = ClassUtils.getMethodIfAvailable(this.bean.getClass(), destroyMethodName);
if (destroyMethod == null) {
// 查找非公共方法
destroyMethod = ClassUtils.getMethod(this.bean.getClass(), destroyMethodName);
}
return destroyMethod;
}
}
catch (Exception ex) {
logger.warn("Could not determine destroy method '" + destroyMethodName + "' on bean with name '" +
this.beanName + "'", ex);
}
return null;
}
/**
* 判断是否有销毁方法
*
* @param bean Bean实例
* @param mbd Bean定义
* @return 如果有销毁方法返回true
*/
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition mbd) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
String destroyMethodName = mbd.getDestroyMethodName();
if (destroyMethodName == null) {
return ClassUtils.hasMethod(bean.getClass(), "close") ||
ClassUtils.hasMethod(bean.getClass(), "shutdown");
}
return StringUtils.hasLength(destroyMethodName);
}
/**
* 执行销毁操作的核心方法
* 按照顺序调用各种销毁机制
*/
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.postProcessors)) {
// 调用DestructionAwareBeanPostProcessor的销毁前置处理
for (DestructionAwareBeanPostProcessor processor : this.postProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
// 调用DisposableBean的destroy方法
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
// 调用自定义销毁方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
// 通过反射调用销毁方法
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(methodToInvoke);
}
}
}
/**
* 调用自定义销毁方法
*
* @param destroyMethod 销毁方法
*/
private void invokeCustomDestroyMethod(final Method destroyMethod) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy method '" + destroyMethod.getName() + "' on bean with name '" +
this.beanName + "'");
}
// 设置方法可访问
ReflectionUtils.makeAccessible(destroyMethod);
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
ReflectionUtils.invokeMethod(destroyMethod, this.bean);
return null;
}, this.acc);
}
else {
// 通过反射调用方法
ReflectionUtils.invokeMethod(destroyMethod, this.bean);
}
}
catch (InvocationTargetException ex) {
String msg = "Invocation of destroy method '" + destroyMethod.getName() + "' failed on bean with name '" +
this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
}
else {
logger.warn(msg + ": " + ex.getTargetException());
}
}
catch (Throwable ex) {
logger.error("Couldn't invoke destroy method '" + destroyMethod.getName() +
"' on bean with name '" + this.beanName + "'", ex);
}
}
}
4. DefaultSingletonBeanRegistry中销毁逻辑
/*
* DefaultSingletonBeanRegistry负责单例Bean的注册和销毁
*/
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
* 销毁所有单例Bean
* 在容器关闭时调用
*/
public void destroySingletons() {
if (logger.isDebugEnabled()) {
logger.debug("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
// 获取所有需要销毁的Bean名称
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
// 按相反顺序销毁Bean
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
// 清理各种缓存
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
}
}
/**
* 销毁单个单例Bean
*
* @param beanName Bean名称
*/
public void destroySingleton(String beanName) {
// 移除单例Bean
removeSingleton(beanName);
// 获取并移除DisposableBean
Object disposableBean;
synchronized (this.disposableBeans) {
disposableBean = this.disposableBeans.remove(beanName);
}
// 执行销毁操作
destroyBean(beanName, disposableBean);
}
/**
* 执行Bean销毁操作
*
* @param beanName Bean名称
* @param bean 要销毁的Bean
*/
protected void destroyBean(String beanName, @Nullable Object bean) {
// 销毁依赖于该Bean的其他Bean
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
// Within synchronized block in order to access dependentBeanMap safely
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isDebugEnabled()) {
logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
if (bean instanceof DisposableBean) {
// 调用DisposableBean的destroy方法
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
// Trigger destruction of contained beans...
destroyBeans(beanName, getContainedBeans(beanName));
// Trigger destruction of dependent beans...
destroyBeans(beanName, getDependentBeans(beanName));
// Actually remove the destroyed bean from the factory...
removeSingleton(beanName);
}
}
5. Bean生命周期中的DisposableBean调用时机
/*
* Bean生命周期完整流程(销毁阶段)
*/
public class BeanLifecycleDestroyDemo {
/**
* 完整的Bean生命周期示例(包括销毁)
*/
public static class LifecycleBean implements
BeanNameAware,
InitializingBean,
DisposableBean {
private String name;
private String beanName;
private Thread backgroundThread;
private boolean destroyed = false;
// 构造方法
public LifecycleBean() {
System.out.println("1. 构造方法被调用");
}
// Setter方法
public void setName(String name) {
System.out.println("2. Setter方法被调用: " + name);
this.name = name;
}
// BeanNameAware接口方法
@Override
public void setBeanName(String name) {
System.out.println("3. BeanNameAware.setBeanName()被调用: " + name);
this.beanName = name;
}
// InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4. InitializingBean.afterPropertiesSet()被调用");
// 启动后台线程
startBackgroundThread();
}
// 自定义初始化方法
public void init() {
System.out.println("5. 自定义init()方法被调用");
}
// DisposableBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("7. DisposableBean.destroy()被调用");
// 执行清理操作
cleanup();
}
// 自定义销毁方法
public void destroyCustom() {
System.out.println("8. 自定义destroyCustom()方法被调用");
}
// 启动后台线程
private void startBackgroundThread() {
backgroundThread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted() && !destroyed) {
try {
System.out.println("后台线程运行中...");
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
System.out.println("后台线程结束");
});
backgroundThread.start();
System.out.println("后台线程已启动");
}
// 清理资源
private void cleanup() {
System.out.println("开始清理资源...");
destroyed = true;
// 停止后台线程
if (backgroundThread != null && backgroundThread.isAlive()) {
backgroundThread.interrupt();
try {
backgroundThread.join(5000); // 等待最多5秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 清理其他资源
System.out.println("资源清理完成");
}
// Getter方法
public String getName() {
return name;
}
}
/**
* DestructionAwareBeanPostProcessor示例
*/
public static class CustomDestructionBeanPostProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("6. DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()被调用: "
+ beanName);
}
@Override
public boolean requiresDestruction(Object bean) {
return bean instanceof LifecycleBean;
}
}
}
6. DisposableBean与@PreDestroy的区别
/*
* DisposableBean与@PreDestroy的对比
*/
public class DestructionComparison {
/**
* 使用DisposableBean的方式
*/
@Component
public static class DisposableBeanExample implements DisposableBean {
@Autowired
private SomeService someService;
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(2);
// 启动定时任务
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean.destroy()执行");
// 清理资源
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
}
/**
* 使用@PreDestroy的方式
*/
@Component
public static class PreDestroyExample {
@Autowired
private SomeService someService;
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(2);
// 启动定时任务
}
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy方法执行");
// 清理资源
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
}
/**
* 使用destroy-method的方式
*/
@Component
public static class DestroyMethodExample {
@Autowired
private SomeService someService;
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(2);
// 启动定时任务
}
public void customDestroy() {
System.out.println("自定义destroy方法执行");
// 清理资源
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
}
/**
* 三种方式混合使用
*/
@Component
public static class MixedDestructionExample
implements InitializingBean, DisposableBean {
@PostConstruct
public void postConstructInit() {
System.out.println("@PostConstruct方法执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet()执行");
}
public void customInit() {
System.out.println("自定义init方法执行");
}
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy方法执行");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean.destroy()执行");
}
public void customDestroy() {
System.out.println("自定义destroy方法执行");
}
}
}
7. 实际应用场景
/*
* DisposableBean的实际应用场景
*/
public class RealWorldDestructionExamples {
/**
* 数据库连接池销毁
*/
@Component
public static class DatabaseConnectionPool implements DisposableBean {
private Connection[] connections;
private ScheduledExecutorService healthCheckScheduler;
@PostConstruct
public void init() {
// 初始化连接池
connections = new Connection[10];
// 创建连接...
// 启动健康检查
healthCheckScheduler = Executors.newSingleThreadScheduledExecutor();
healthCheckScheduler.scheduleAtFixedRate(this::checkConnections,
30, 30, TimeUnit.SECONDS);
}
@Override
public void destroy() throws Exception {
System.out.println("关闭数据库连接池...");
// 关闭健康检查调度器
if (healthCheckScheduler != null) {
healthCheckScheduler.shutdown();
try {
if (!healthCheckScheduler.awaitTermination(30, TimeUnit.SECONDS)) {
healthCheckScheduler.shutdownNow();
}
} catch (InterruptedException e) {
healthCheckScheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
// 关闭所有数据库连接
for (int i = 0; i < connections.length; i++) {
if (connections[i] != null) {
try {
connections[i].close();
System.out.println("连接 " + i + " 已关闭");
} catch (SQLException e) {
System.err.println("关闭连接 " + i + " 时出错: " + e.getMessage());
}
}
}
System.out.println("数据库连接池已完全关闭");
}
private void checkConnections() {
// 健康检查逻辑
}
}
/**
* 文件监听器销毁
*/
@Component
public static class FileWatcher implements DisposableBean {
@Value("${watch.directory:/tmp}")
private String watchDirectory;
private WatchService watchService;
private Thread watchThread;
private volatile boolean running = true;
@PostConstruct
public void init() throws IOException {
// 初始化文件监听服务
watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get(watchDirectory);
path.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);
// 启动监听线程
startWatching();
}
private void startWatching() {
watchThread = new Thread(() -> {
while (running) {
try {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
handleFileEvent(event);
}
key.reset();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (Exception e) {
if (running) {
System.err.println("文件监听出错: " + e.getMessage());
}
}
}
System.out.println("文件监听线程已停止");
});
watchThread.setDaemon(false);
watchThread.start();
}
private void handleFileEvent(WatchEvent<?> event) {
// 处理文件事件
System.out.println("文件事件: " + event.kind() + " - " + event.context());
}
@Override
public void destroy() throws Exception {
System.out.println("停止文件监听器...");
// 停止监听
running = false;
// 关闭WatchService
if (watchService != null) {
try {
watchService.close();
} catch (IOException e) {
System.err.println("关闭WatchService时出错: " + e.getMessage());
}
}
// 中断监听线程
if (watchThread != null && watchThread.isAlive()) {
watchThread.interrupt();
try {
watchThread.join(5000); // 等待最多5秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("文件监听器已停止");
}
}
/**
* 缓存管理器销毁
*/
@Component
public static class CacheManager implements DisposableBean {
private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
private ScheduledExecutorService cleanupScheduler;
private final List<CacheListener> listeners = new CopyOnWriteArrayList<>();
@PostConstruct
public void init() {
// 启动定期清理任务
cleanupScheduler = Executors.newSingleThreadScheduledExecutor();
cleanupScheduler.scheduleAtFixedRate(this::cleanupExpiredEntries,
60, 60, TimeUnit.SECONDS);
}
@Override
public void destroy() throws Exception {
System.out.println("销毁缓存管理器...");
// 通知所有监听器
for (CacheListener listener : listeners) {
try {
listener.onCacheDestroy();
} catch (Exception e) {
System.err.println("缓存监听器销毁出错: " + e.getMessage());
}
}
// 关闭清理调度器
if (cleanupScheduler != null) {
cleanupScheduler.shutdown();
try {
if (!cleanupScheduler.awaitTermination(30, TimeUnit.SECONDS)) {
cleanupScheduler.shutdownNow();
}
} catch (InterruptedException e) {
cleanupScheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
// 清空缓存
int cacheSize = cache.size();
cache.clear();
// 记录销毁信息
System.out.println("缓存管理器已销毁,清理了 " + cacheSize + " 个缓存项");
}
private void cleanupExpiredEntries() {
// 清理过期缓存项
long now = System.currentTimeMillis();
cache.entrySet().removeIf(entry -> {
CacheEntry cacheEntry = entry.getValue();
return cacheEntry.getExpiryTime() < now;
});
}
// 缓存实体类
private static class CacheEntry {
private final Object value;
private final long expiryTime;
public CacheEntry(Object value, long expiryTime) {
this.value = value;
this.expiryTime = expiryTime;
}
public Object getValue() { return value; }
public long getExpiryTime() { return expiryTime; }
}
// 缓存监听器接口
public interface CacheListener {
void onCacheDestroy();
}
}
/**
* 网络客户端销毁
*/
@Component
public static class NetworkClient implements DisposableBean {
@Value("${server.host:localhost}")
private String host;
@Value("${server.port:8080}")
private int port;
private Socket socket;
private ExecutorService requestExecutor;
private volatile boolean connected = false;
@PostConstruct
public void init() throws IOException {
// 建立网络连接
connect();
// 初始化请求执行器
requestExecutor = Executors.newFixedThreadPool(5);
}
private void connect() throws IOException {
socket = new Socket(host, port);
connected = true;
System.out.println("已连接到服务器 " + host + ":" + port);
}
@Override
public void destroy() throws Exception {
System.out.println("关闭网络客户端...");
// 标记断开连接
connected = false;
// 关闭请求执行器
if (requestExecutor != null) {
requestExecutor.shutdown();
try {
if (!requestExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
requestExecutor.shutdownNow();
}
} catch (InterruptedException e) {
requestExecutor.shutdownNow();
Thread.currentThread().interrupt();
}
}
// 关闭Socket连接
if (socket != null && !socket.isClosed()) {
try {
socket.close();
System.out.println("Socket连接已关闭");
} catch (IOException e) {
System.err.println("关闭Socket时出错: " + e.getMessage());
}
}
System.out.println("网络客户端已完全关闭");
}
public boolean isConnected() {
return connected && socket != null && !socket.isClosed();
}
}
}
8. 最佳实践和注意事项
/*
* DisposableBean最佳实践
*/
public class DestructionBestPractices {
/**
* 正确的DisposableBean实现
*/
@Component
public static class GoodExample implements DisposableBean {
@Autowired
private DataSource dataSource;
private ScheduledExecutorService scheduler;
private List<Closeable> resources = new ArrayList<>();
@PostConstruct
public void init() {
// 初始化调度器
scheduler = Executors.newScheduledThreadPool(2);
// 初始化资源
try {
Connection conn = dataSource.getConnection();
resources.add(conn);
} catch (SQLException e) {
throw new RuntimeException("初始化资源失败", e);
}
}
@Override
public void destroy() throws Exception {
// 记录销毁开始
System.out.println("开始销毁Bean...");
// 按相反顺序关闭资源
closeResources();
// 关闭调度器
shutdownScheduler();
// 记录销毁完成
System.out.println("Bean销毁完成");
}
private void closeResources() {
// 按相反顺序关闭资源(后创建的先关闭)
for (int i = resources.size() - 1; i >= 0; i--) {
Closeable resource = resources.get(i);
try {
if (resource != null) {
resource.close();
System.out.println("资源已关闭: " + resource.getClass().getSimpleName());
}
} catch (IOException e) {
// 记录日志但不抛出异常
System.err.println("关闭资源时出错: " + e.getMessage());
}
}
resources.clear();
}
private void shutdownScheduler() {
if (scheduler != null) {
scheduler.shutdown();
try {
// 等待优雅关闭
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
System.out.println("调度器强制关闭");
scheduler.shutdownNow();
// 再次等待
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("调度器无法关闭");
}
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
System.out.println("调度器已关闭");
}
}
}
/**
* 避免的错误实现
*/
@Component
public static class BadExample implements DisposableBean {
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(5);
}
@Override
public void destroy() throws Exception {
// 错误1: 抛出异常而不是记录日志
if (scheduler == null) {
throw new IllegalStateException("调度器未初始化");
}
// 错误2: 执行耗时操作
Thread.sleep(10000); // 避免这样做
// 错误3: 不处理异常
scheduler.shutdownNow(); // 应该处理可能的异常
// 错误4: 复杂的业务逻辑
performComplexCleanupLogic(); // 应该移到专门的清理方法中
}
private void performComplexCleanupLogic() {
// 复杂的清理逻辑不应该在这里执行
}
}
/**
* 现代化的替代方案
*/
@Component
public static class ModernApproach {
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
scheduler = Executors.newScheduledThreadPool(2);
}
// 使用@PreDestroy替代DisposableBean
@PreDestroy
public void cleanup() {
System.out.println("使用@PreDestroy清理资源");
if (scheduler != null) {
scheduler.shutdown();
}
}
// 或者使用try-with-resources模式
public void useResource() {
try (CloseableResource resource = new CloseableResource()) {
// 使用资源
} catch (IOException e) {
// 处理异常
}
}
// 可关闭的资源类
private static class CloseableResource implements AutoCloseable {
@Override
public void close() throws IOException {
System.out.println("资源已关闭");
}
}
}
/**
* 确保幂等性的实现
*/
@Component
public static class IdempotentExample implements DisposableBean {
private volatile boolean destroyed = false;
private final Object destroyLock = new Object();
@Override
public void destroy() throws Exception {
// 确保幂等性
synchronized (destroyLock) {
if (destroyed) {
System.out.println("Bean已销毁,跳过重复销毁");
return;
}
System.out.println("执行销毁操作...");
// 执行实际的销毁逻辑
destroyed = true;
System.out.println("销毁操作完成");
}
}
}
}
9. 核心设计要点总结
9.1 设计目的
- 提供标准的Bean销毁回调机制
- 确保Bean在被回收前完成必要的清理工作
- 解耦Bean的清理逻辑与业务逻辑
9.2 调用时机
- ApplicationContext关闭
- BeanFactory销毁Bean
- destroy()方法调用
- Bean被垃圾回收
9.3 使用建议
- 优先使用@PreDestroy:减少与Spring框架的耦合
- 资源清理:关闭数据库连接、文件句柄、网络连接等
- 异常处理:适当处理清理过程中可能发生的异常,避免抛出异常
- 幂等性:确保销毁方法可以被多次调用
- 优雅关闭:给资源足够的时间进行优雅关闭
9.4 与其他销毁机制的关系
- 执行顺序:DestructionAwareBeanPostProcessor → @PreDestroy → DisposableBean → destroy-method
- 互斥性:四种方式可以同时使用,但要注意执行顺序
- 优先级:通常按照上述顺序执行
9.5 常见应用场景
- 数据库连接池关闭
- 文件监听器停止
- 缓存清理
- 网络连接关闭
- 定时任务调度器停止
- 线程池关闭
9.6 最佳实践
- 实现幂等性,确保可以多次调用
- 优雅关闭资源,避免强制终止
- 记录日志而不是抛出异常
- 按正确的顺序关闭资源
- 避免在销毁方法中执行耗时操作
DisposableBean作为Spring框架的重要组成部分,为开发者提供了灵活而强大的Bean销毁机制,是理解和使用Spring IoC容器生命周期管理的关键知识点。

6427

被折叠的 条评论
为什么被折叠?



