接着前篇,有初始化对应着就有销毁。Spring提供了多种方式的销毁回调方法,这些方法在手动关闭容器的时候就会触发。
销毁回调方式:
后置处理器DestructionAwareBeanPostProcessor
的postProcessBeforeDestruction()
方法,此方式是对所有bean有效
在类方法上使用@PreDestroy
注解
实现接口DisposableBean
的destory()
方法
自定义回调方法,@Bean(destroyMethod = "beanDestoryCallbackMethod")
实现AutoCloseable
接口或者Closeable
接口的bean(当且仅当此bean没有任何自定义销毁回调,也就是说此bean没有使用前面的2,3,4这三种方式)
仍然按照前篇的思路,先演示,再提疑问,再读源码。
演示案例 自定义一个实现前面四种方式中的后三种方式的bean,实现DisposableBean
接口,在bean中使用@PreDestory
注解。然后在注入容器的时候使用@Bean
注解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 package com.ubuntuvim.spring.createbean;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;import org.springframework.context.support.AbstractApplicationContext;import javax.annotation.PreDestroy;import java.io.IOException;public class DestoryCallbackBean implements DisposableBean , /*Closeable , */AutoCloseable { @Override public void destroy () throws Exception { System.out.println("执行销毁回调DisposableBean.destory()方法" ); } private void beanDestoryCallbackMethod () { System.out.println("执行销毁回调@Bean(destroyMethod = \"beanDestoryCallbackMethod\")的方法" ); } private void beanDestoryCallbackMethod (Fruit apple) { apple.eatable(); System.out.println("执行销毁回调@Bean(destroyMethod = \"beanDestoryCallbackMethod\")的方法" ); } @PreDestroy public void twoDestroy () { System.out.println("执行销毁回调@PreDestroy注解的回调方法twoDestroy()" ); } @PreDestroy public void oneDestroy () { System.out.println("执行销毁回调@PreDestroy注解的回调方法oneDestroy()" ); } @Override public void close () throws IOException { System.out.println("执行销毁回调Closeable.close()方法" ); } public void shutdown () { System.out.println("执行销毁回调shutdown()方法" ); } }
还有一种默认的回调,就是实现AutoCloseable
接口或者Closeable
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.ubuntuvim.spring.createbean;import org.springframework.stereotype.Component;import java.io.Closeable;@Component public class SimpleDestoryBean implements Closeable { @Override public void close () { System.out.println("既不实现DispoableBean接口,也没有自定义的销毁方法的情况下执行最后默认的AutoCloseable.close方法" ); } }
再定义一个后置处理器,实现DestructionAwareBeanPostProcessor
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Component public class MyDestructionAwareBeanPostProcessorImpl implements DestructionAwareBeanPostProcessor { @Override public void postProcessBeforeDestruction (Object bean, String beanName) throws BeansException { if ("DestoryCallbackBean" .equalsIgnoreCase(beanName)) System.out.println("执行销毁回调DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()方法" ); } @Override public boolean requiresDestruction (Object bean) { return true ; } }
最后,通过@Bean
注入到容器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.ubuntuvim.spring.createbean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@ComponentScan @Configuration public class Config { @Bean(destroyMethod = "beanDestoryCallbackMethod") public DestoryCallbackBean destoryCallbackBean () { return new DestoryCallbackBean(); } }
运行案例;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.ubuntuvim.spring.createbean;import org.springframework.beans.factory.support.RootBeanDefinition;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.AbstractApplicationContext;public class CreateBeanTest { public static void main (String[] args) { AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class); applicationContext.close(); } }
applicationContext.close();
这句代码非常关键,必须要手动关闭容器才会触发销毁回调的执行 。你可以把这行代码注释掉在运行,注释掉之后不会打印如下的日志。即使是后置处理器接口也不会执行。
1 2 3 4 5 6 执行销毁回调DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()方法 执行销毁回调@PreDestroy注解的回调方法oneDestroy() 执行销毁回调@PreDestroy注解的回调方法twoDestroy() 执行销毁回调DisposableBean.destory()方法 执行销毁回调@Bean(destroyMethod = "beanDestoryCallbackMethod")的方法 既不实现DispoableBean接口,也没有自定义的销毁方法的情况下执行最后默认的AutoCloseable.close方法
Spring源码 接下来,我们从Spring源码入手,看看这些回调是在什么地方执行的。首先在main
方法中的close
方法上打个断点,然后用debug方式运行main
方法。
进入到close()
方法的逻辑里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override public void close () { synchronized (this .startupShutdownMonitor) { doClose(); if (this .shutdownHook != null ) { try { Runtime.getRuntime().removeShutdownHook(this .shutdownHook); } catch (IllegalStateException ex) { } } } }
按照Spring框架的尿性,不用想,具体处理逻辑肯定是在doClose()
里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 protected void doClose () { if (this .active.get() && this .closed.compareAndSet(false , true )) { if (logger.isDebugEnabled()) { logger.debug("Closing " + this ); } LiveBeansView.unregisterApplicationContext(this ); try { publishEvent(new ContextClosedEvent(this )); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent" , ex); } if (this .lifecycleProcessor != null ) { try { this .lifecycleProcessor.onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close" , ex); } } destroyBeans(); closeBeanFactory(); onClose(); if (this .earlyApplicationListeners != null ) { this .applicationListeners.clear(); this .applicationListeners.addAll(this .earlyApplicationListeners); } this .active.set(false ); } }
这个方法做的事情很多,主要有:触发所有bean的销毁回调、发布关闭事件、执行bean的生命周期关闭方法、设置容器的状态为关闭、执行销毁的后置处理器。
本篇重点关注的是destroyBeans()
方法。这个方法里面会执行自定义的销毁方法,@PreDestory
注释的方法,后置处理器的postProcessBeforeDestruction()
方法。
进入destoryBeans()
方法后,发现这还不是最后的执行逻辑,这个方法又交给DefaultListableBeanFactory
的destroySingletons()
方法处理。
进入destorySingletons()
方法后,发现还不是最好的执行逻辑,它的实现是调用父类的同名方法,继续进入它父类同名方法。DefaultSingletonBeanRegistry
的destroySingletons()
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public void destroySingletons () { if (logger.isTraceEnabled()) { logger.trace("Destroying singletons in " + this ); } synchronized (this .singletonObjects) { this .singletonsCurrentlyInDestruction = true ; } String[] disposableBeanNames; synchronized (this .disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this .disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1 ; i >= 0 ; i--) { destroySingleton(disposableBeanNames[i]); } this .containedBeanMap.clear(); this .dependentBeanMap.clear(); this .dependenciesForBeanMap.clear(); clearSingletonCache(); }
最核心的逻辑在for循环里面,遍历所有可销毁的bean数组disposableBeanNames
。
继续一步步进入调用逻辑,按照如下调用顺序就可以找到最后的执行逻辑:
DefaultSingletonBeanRegistry.destroySingletons() -> DefaultSingletonBeanRegistry.destroySingleton() -> DisposableBeanAdapter.destroy()
DisposableBeanAdapter.destory()才是最后的处理逻辑。不得不说这个调用层次实在是太深了!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public void destroy () { if (!CollectionUtils.isEmpty(this .beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this .beanPostProcessors) { processor.postProcessBeforeDestruction(this .bean, this .beanName); } } if (this .invokeDisposableBean) { if (logger.isTraceEnabled()) { logger.trace("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) 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(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } } }
首先遍历后置处理器的postProcessBeforeDestruction()
方法,这个方法是对所有bean生效的。
@PreDestory
注解标注的方法也是通过后置处理器执行的。当遍历到InitDestroyAnnotationBeanPostProcessor
这个后置处理器的时候,执行的原理和初始化回调是一样的,底层都是通过反射实现。
然后是执行单个bean实现的DisposableBean
接口的destory()
方法,
最后是执行在@Bean
中自定义的销毁回调方法。
执行接口Closable
接口的close()
方法。
到此,已经把所有的销毁回调的执行都介绍完了。你是否看懂了呢??