【JAVA】【Spring】小记一下ApplicationListenerDetector

151 阅读3分钟

背景

前面查问题时发现了这个Listener还挺特殊的,单独add进的工厂,所以发散下,稍微搞清楚些。

边界明确,不要死纠,理解设计,拟合想法。

执行

当时我们发现了,这个类在refreshContext注册BeanPostProcessors时,手动add了一下,但是其实在这之前,工厂中就已经存在了如图,很好奇。

image.png

直接Debug ApplicationListenerDetector的构造方法,看看都有什么地方用到了。

(1)直接prepareBeanFactory直接添加

image.png

(2)然后就是我们一开始截图的,refreshContext注册BeanPostProcessors时直接添加

image.png

问题

  • 为什么要add两次这个类?

(1)中进行add的原因,是因为各类开源组件都应按合理的方式加入spring工厂启动时预埋的各种点/口子,那么自然可能有实现了ApplicationListener的情况,自然要在prepare工厂时就加好这个ListenerDetector来监听,以尽早让其进入工厂开始探测。

否则呢?

否则可能出现:实现了BeanFactoryPostProcessor的类,早于这个实现了BeanPostProcessor的ApplicationListenerDetector进入工厂,没有被探测到加入工厂的listener队列。 原因:Spring工厂流程顺序 image.png

  • 为什么要靠这个ApplicationListenerDetector来监听

image.png

  • 1、正常会在启动流程中registerListeners时全加入,但getBeanOfType不可靠?

源码直接写了:不支持获取到嵌套bean,但实话实说我都不知道springboot里哪里搞嵌套类,可能这个用法太老了吧

image.png
  • 2、为什么要Transient field?

刚开始纠结很久怎么也看不懂ApplicationListenerDetector二段注释说的意思,因为陷在了序列化这个事本身上了。

发散:注释中提到的DisposableBeanAdapter是spring对各种需要destroy方法的bean的适配,看源码是在doCreateBean时判断bean自身是否要加入工厂的disposableBeans销毁list。

判断依据:either DestructionAwareBeanPostProcessor or 有自己写的destory方法/close方法,这个只是更规范。唉……一堆历史遗留隐式也没个说明Note。

重点在于:defensively 防御性编程

使用标准的Java序列化,这个后处理器一开始就不会作为DisposableBeanAdapter的一部分进行序列化。
然而,使用其他序列化机制,DisposableBeanAdapter.writePlace可能根本不会被使用,
因此我们防御性地将此后处理器的字段状态标记为瞬态。

大言不惭的说,这段话根本不通,什么叫“使用标准的Java序列化,这个后处理器一开始就不会作为DisposableBeanAdapter的一部分进行序列化。”啊????

JAVA又不是不能多implement,而且这和“作为DisposableBeanAdapter的一部分”有什么联系吗?

我只能认为这段注释就是不通顺的。但总之他防御性编程了。

ApplicationListenerDetector会被设为disposableBeans的销毁后处理器,如果disposableBean序列化,ApplicationListenerDetector内部字段traisent了不会报错(不信任disposableBean序中符合wirteReplace这一序列化范围的机制实现对于要序列化哪些的筛选),但说实话你为啥不直接implement Serializable呢?这样就不用担心报错了。

只能猜测是本身就不希望ApplicationListenerDetector一同被序列化,所以不实现Serializable,但又怕wirteReplace不生效?但可能吗?

恍然大悟,这就是防御性编程。

ok大师我悟了

这就是源码,不是第一编写人,谁猜得透,学个思想得了