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 {
@Override
public 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 {
@Override
public 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 DisposableBean
destroyMethodName = 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是一个变量
@Nullable
volatile String resolvedDestroyMethodName;
2.4.1.1.1.1.1.2 getDestroyMethodName方法
这个一般和MergedBeanDefinitionPostProcess接口一起使用
@Nullable
public String getDestroyMethodName() {
return this.destroyMethodName;
}
一般在MergedBeanDefinitionPostProcess接口实现类中使用setDestroyMethodName方法:
@Component
public class User implements MergedBeanDefinitionPostProcessor {
@Override
public 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 {
@Override
public 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);
}