1.Bean销毁是发送在Spring容器关闭过程中的
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = (UserService) context.getBean("userService");userService.test();// 容器关闭context.close();
2.在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean
- 当前Bean是否实现了DisposableBean接口
- 或者,当前Bean是否实现了AutoCloseable接口
- BeanDefinition中是否指定了destroyMethod
- 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
a. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
b. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean - 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)
2.1 什么是DisposableBean接口
在Spring框架中,DisposableBean是一个接口,它定义了一个单一的方法destroy,用于在Spring容器关闭时或一个由Spring管理的Bean不再需要时执行特定的清理操作。当一个Bean实现了DisposableBean接口,Spring容器会在销毁该Bean之前调用其destroy()方法。
2.1.1DisposableBean接口代码
public interface DisposableBean {void destroy() throws Exception;}
2.1.2 DisposableBean接口实现类的代码
2.1.3测试 在容器关闭的时候,会调用close方法
2.2 什么AutoCloseable接口 其实也实现了close方法
AutoCloseable意为可自动关闭的
但是AutoCloseable的代码比较复杂,就不写了
2.2.1AutoCloseable接口的实现类
class MyResource implements AutoCloseable {@Overridepublic void close() throws Exception {System.out.println(0);/*关闭资源*/}
}
2.3 指定了destroyMethod是什么意思啊?
2.3.1
添加了@PreDestroy ,@PreDestroy注解用于在Bean销毁前执行清理操作。在方法上添加@PreDestroy注解后,Spring容器会在Bean销毁前自动调用该方法,以完成清理工作。
2.3.2
自定义的方法名字,Spring会将此方法的名字作为销毁方法的名字
@Component
public class MyMergedBeanDefinitionPostProcessor1 implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("xxx")) {//自定义销毁方法的名字beanDefinition.setDestroyMethodName("a");}}public void a(){}
}
2.4判断 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
2.4.1 在docreatebean方法中
// Register bean as disposable.
try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}return exposedObject;
2.4.1.1 registerDisposableBeanIfNecessary方法
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()) {// Register a DisposableBean implementation that performs all destruction// work for the given bean: DestructionAwareBeanPostProcessors,// DisposableBean interface, custom destroy method.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));}else {// A bean with a custom scope...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, getBeanPostProcessorCache().destructionAware, acc));}}
}
2.4.1.1.1 requiresDestruction方法判断: 这个方法是重点
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessorCache().destructionAware))));
}
其中第一个判断方法:
2.4.1.1.1.1 DisposableBeanAdapter.hasDestroyMethod 方法:
bean对象是不是实现了DisposableBean 接口 和AutoCloseable 接口
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {return true;}return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}
2.4.1.1.1.1.1
其中的inferDestroyMethodIfNecessary方法:判断是不是有指定的destroymethod
private static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {String destroyMethodName = beanDefinition.resolvedDestroyMethodName;if (destroyMethodName == null) {destroyMethodName = beanDefinition.getDestroyMethodName(); //if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||(destroyMethodName == null && bean instanceof AutoCloseable)) {// Only perform destroy method inference or Closeable detection// in case of the bean not explicitly implementing DisposableBeandestroyMethodName = null;if (!(bean instanceof DisposableBean)) {try {destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();}catch (NoSuchMethodException ex) {try {destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();}catch (NoSuchMethodException ex2) {// no candidate destroy method found}}}}beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");}return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
}
2.4.1.1.1.1.1.1 beanDefinition.resolvedDestroyMethodName是一个变量
@Nullablevolatile String resolvedDestroyMethodName;
2.4.1.1.1.1.1.2 getDestroyMethodName方法
这个一般和MergedBeanDefinitionPostProcess接口一起使用
@Nullablepublic String getDestroyMethodName() {return this.destroyMethodName;}
一般在MergedBeanDefinitionPostProcess接口实现类中使用setDestroyMethodName方法:
@Component
public class User implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {beanDefinition.setDestroyMethodName("a");}
}
2.4.1.1.1.1.1.3 AbstractBeanDefinition.INFER_METHOD变量
这里特指在beanDefinition.setDestroyMethodName设定(inferred)
常量,表示容器应该尝试推断bean的销毁方法名称,而不是显式指定方法名称。
public static final String INFER_METHOD = "(inferred)";
举例:在MergedBeanDefinitionPostProcess接口实现类中使用setDestroyMethodName方法
@Component
public class MyMergedBeanDefinitionPostProcessor1 implements MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("xxx")) {//设置Spring指定的特定的名字"(inferred)"beanDefinition.setDestroyMethodName("(inferred)");、//自定义销毁方法的名字beanDefinition.setDestroyMethodName("customDestory");}}}
2.4.1.1.1.1.1.3.1 CLOSE_METHOD_NAM变量
指定了特定的销毁方法的名字:“(inferred)”,则会将该Bean中close()和shutdown()作为销毁方法(前提是Bean里面有这两个方法)
private static final String CLOSE_METHOD_NAME = "close";
bean.getClass().getMethod(CLOSE_METHOD_NAME).getName()
2.4.1.1.1.1.1.3.2 CLOSE_METHOD_NAM变量
第二个方法:
2.4.1.1.1.2 hasDestructionAwareBeanPostProcessors 方法:判断有无实现DestructionAwareBeanPostProcessor
protected boolean hasDestructionAwareBeanPostProcessors() {return !getBeanPostProcessorCache().destructionAware.isEmpty();}
2.4.1.1.1.2.1 补充知识 DestructionAwareBeanPostProcessor接口
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {//postProcessBeforeDestruction方法用来进行销毁前置处理,做完这个方法后,调用close方法void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;//requiresDestruction方法是用来筛选哪些bean可以执行postProcessBeforeDestruction方法。default boolean requiresDestruction(Object bean) {return true;}}
2.4.1.1.1.2.2 getBeanPostProcessorCache()方法获取存储PostProcessor的对象,判断其中的destructionAware集合是不是空
BeanPostProcessorCache getBeanPostProcessorCache() {BeanPostProcessorCache bpCache = this.beanPostProcessorCache;if (bpCache == null) {bpCache = new BeanPostProcessorCache();for (BeanPostProcessor bp : this.beanPostProcessors) {if (bp instanceof InstantiationAwareBeanPostProcessor) {bpCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bp);if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {bpCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bp);}}if (bp instanceof DestructionAwareBeanPostProcessor) {bpCache.destructionAware.add((DestructionAwareBeanPostProcessor) bp);}if (bp instanceof MergedBeanDefinitionPostProcessor) {bpCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bp);}}this.beanPostProcessorCache = bpCache;}return bpCache;}
第三个方法:
2.4.1.1.1.3 DisposableBeanAdapter.hasApplicableProcessors 方法
本质 调用DestructionAwareBeanPostProcessor 的requiresDestruction方法
public static boolean hasApplicableProcessors(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {if (!CollectionUtils.isEmpty(postProcessors)) {for (DestructionAwareBeanPostProcessor processor : postProcessors) {if (processor.requiresDestruction(bean)) {return true;}}}return false;}
2.4.1.2 registerDisposableBean方法
对需要销毁的Bean,封装成DisposableBeanAdapter对象,最后调用registerDisposableBean()方法将DisposableBeanAdapter对象放入disposableBeans
public void registerDisposableBean(String beanName, DisposableBean bean) {synchronized (this.disposableBeans) {this.disposableBeans.put(beanName, bean);}}
2.4.1.2.1 disposableBeans 是存放要销毁的bean的集合
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
2.4.1.2.2 DisposableBeanAdapter 对象
这里涉及到一个设计模式:适配器模式 ,在销毁时,Spring会找出定义了销毁逻辑的Bean。 但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了 AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属 于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。 所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {Assert.notNull(bean, "Disposable bean must not be null");this.bean = bean;this.beanName = beanName;this.invokeDisposableBean =(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();this.acc = acc;String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {this.destroyMethodName = destroyMethodName;Method destroyMethod = determineDestroyMethod(destroyMethodName);if (destroyMethod == null) {if (beanDefinition.isEnforceDestroyMethod()) {throw new BeanDefinitionValidationException("Could not find a destroy method named '" +destroyMethodName + "' on bean with name '" + beanName + "'");}}else {if (destroyMethod.getParameterCount() > 0) {Class<?>[] paramTypes = destroyMethod.getParameterTypes();if (paramTypes.length > 1) {throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +beanName + "' has more than one parameter - not supported as destroy method");}else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +beanName + "' has a non-boolean parameter - not supported as destroy method");}}destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);}this.destroyMethod = destroyMethod;}this.beanPostProcessors = filterPostProcessors(postProcessors, bean);}