Spring DisposableBean 源码详解(详细注释版)

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 调用时机

  1. ApplicationContext关闭
  2. BeanFactory销毁Bean
  3. destroy()方法调用
  4. Bean被垃圾回收

9.3 使用建议

  • 优先使用@PreDestroy:减少与Spring框架的耦合
  • 资源清理:关闭数据库连接、文件句柄、网络连接等
  • 异常处理:适当处理清理过程中可能发生的异常,避免抛出异常
  • 幂等性:确保销毁方法可以被多次调用
  • 优雅关闭:给资源足够的时间进行优雅关闭

9.4 与其他销毁机制的关系

  • 执行顺序:DestructionAwareBeanPostProcessor → @PreDestroy → DisposableBean → destroy-method
  • 互斥性:四种方式可以同时使用,但要注意执行顺序
  • 优先级:通常按照上述顺序执行

9.5 常见应用场景

  • 数据库连接池关闭
  • 文件监听器停止
  • 缓存清理
  • 网络连接关闭
  • 定时任务调度器停止
  • 线程池关闭

9.6 最佳实践

  • 实现幂等性,确保可以多次调用
  • 优雅关闭资源,避免强制终止
  • 记录日志而不是抛出异常
  • 按正确的顺序关闭资源
  • 避免在销毁方法中执行耗时操作

DisposableBean作为Spring框架的重要组成部分,为开发者提供了灵活而强大的Bean销毁机制,是理解和使用Spring IoC容器生命周期管理的关键知识点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值