当前位置: 首页 > news >正文

java spring 09 Bean的销毁过程 上 在docreatebean中登记要销毁的bean

1.Bean销毁是发送在Spring容器关闭过程中的

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = (UserService) context.getBean("userService");userService.test();// 容器关闭context.close();

2.在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean

  1. 当前Bean是否实现了DisposableBean接口
  2. 或者,当前Bean是否实现了AutoCloseable接口
  3. BeanDefinition中是否指定了destroyMethod
  4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    a. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
    b. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
  5. 把符合上述任意一个条件的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);}
http://www.lryc.cn/news/343295.html

相关文章:

  • 杰发科技AC7801——支持的纠错功能
  • spring boot运行过程中动态加载Controller
  • 学习软考----数据库系统工程师25
  • RTMP 直播推流 Demo(一)—— 项目配置与视频预览
  • 安卓获取SHA
  • 【Qt 学习笔记】Qt常用控件 | 输入类控件 | Dial的使用及说明
  • 【C语言】项目实践-贪吃蛇小游戏(Windows环境的控制台下)
  • 在做题中学习(50):搜索插入位置
  • 【mysql】mysql单表查询、多表查询、分组查询、子查询等案例详细解析
  • 【Gateway远程开发】0.5GB of free space is necessary to run the IDE.
  • 普通组件的注册-局部注册和全局注册
  • Apache Dubbo知识点表格总结
  • 电路板/硬件---器件
  • STC15W1K16S和VC6.0串口通讯收发测试实例
  • Python程序设计 函数(三)
  • linux之ssh
  • excel如何将多列数据转换为一列?
  • 【Java 刷题记录】前缀和
  • NVIDIA: RULER新测量方法让大模型现形
  • 2024数学-微积分和线性代数/本科研究生专业考试/考研/论文/重点公式考点汇总/最难公式投票
  • 代码随想录训练营Day33(贪心算法):Leetcode1005、134、135(难得有一天能完全独立做出题目)
  • Flutter笔记:Widgets Easier组件库(12)使用消息吐丝(Notify Toasts)
  • 从《春色寄情人》学习如何面对死亡
  • 使用moveit控制机械臂
  • Mysql报错红温集锦(一)(ipynb配置、pymysql登录、密码带@、to_sql如何加速、触发器SIGNAL阻止插入数据)
  • ASP.NET Core SignalR 配置与集成测试究极指南
  • JENKINS 安装,学习运维从这里开始
  • 大语言模型从Scaling Laws到MoE
  • 四级英语翻译随堂笔记
  • Nacos支持的配置格式及其在微服务架构中的应用