第一节介绍 Spring 启动 (链接) 时,介绍 AbstractApplicationContext 的过销毁过程,主要是调用了内部的 destroyBeans 方法,这节便来介绍 bean 的销毁过程。
一. 销毁流程
destroyBeans 方法内部委托给了 DefaultSingletonBeanRegistry 的 destroySingletons 方法。destroySingletons 方法如下,比较清晰:
前面介绍过,DefaultSingletonBeanRegistry 用一个 Map 缓存着所有的单例实例,对于对象的销毁,只要简单的将其从 Map 中移除就行。主要处理的是依赖关系下的 bean 销毁顺序以及回调接口的处理。上面先对 disposableBeans 中所涉及到的 bean 逐个进行销毁,然后再清理所有的依赖关系和缓存的单例实例。
上一节提到,disposableBeans 中存放的是存在销毁时需要进行方法回调的 DisposableBeanAdapter 对象,key 为对应的 bean name,会在 bean 初始化后进行判断并且存入。这里会优先处理这些 bean 的销毁,下面重点介绍下 destroySingleton 方法。
二.destroySingleton
如上描述了该方法的大致过程,分别为
- 将 DefaultSingletonBeanRegistry 中缓存的各种单例实例清除掉
- 执行 disposableBeans.remove 方法,移除该 beanName,这里会返回一个 DisposableBean 对象
- 删除 dependentBeanMap 中 beanName 的内容,也是执行 remove 的方法,会返回依赖于 beanName 的其他 bean name 列表,再依次调用 destorySingleton 销毁这些 bean
- 对当前的 DisposableBean 执行 destory
- 删除 containedBeanMap 中 beanName 的内容,执行的 remove 方法,hi 返回 beanName 依赖的其他 bean name 列表,再依次调用 destorySingleton 销毁这些 bean
从而具体的回调发生在第 4 步,开头提到,bean 在实例化后会以 DisposableBeanAdapter 存放进 disposableBeans 中,从而该类实现了具体的回调过程。
三.DisposableBeanAdapter
DisposableBeanAdapter 的结构如下,其实现了 DisposableBean 接口,因而可以如上面说的,在 destroySingleton 方法进行回调。它在构造方法中对几个重要的属性进行了赋值,用于存储销毁动作相关的信息,包括:
- Bean:待销毁 bean 对象
- beanName:待销毁 bean 的 beanName
- destroyMethodName:待销毁要调用的方法,该方法来源于 destory-method 配置项,如果为(inferred),则会将回调方法赋值为 close 或者 shutdown
- destoryMethod:destoryMethodName 对应的 Method 对象
- beanPostProcessors:需要处理该 bean 的 DestructionAwareBeanPostProcessor 回调列表。在实例化 DisposableBeanAdapter 对象时,会过滤系统中的 BeanPostProcessor 列表,找出实现 DestructionAwareBeanPostProcessor 接口,且 requiresDestruction 方法返回 true 的实例,用于后续进行回调。(InitDestroyAnnotationBeanPostProcessor 类实现了该方法,用以回调 @PreDestory 注解的方法,CommonAnnotationBeanPostProcessor 继承自该类,设置了 destroyAnnotationType 为 PreDestroy.class)
当按照第(二)部分第 4 步执行时,该类会按照如下顺序执行销毁动作:
- 如果 beanPostProcessors 列表不为空,则回调 DestructionAwareBeanPostProcessor 的 postProcessBeforeDestruction 方法,即执行 @PreDestory 注解方法
- 如果实现了 DisposableBean,则回调 DisposableBean 的 destroy 方法,即执行 DisposableBean 接口方法
- 如果配置了 destroy-method,则执行配置的方法,即执行 destory-method 配置方法
个人公众号:啊驼