三万字盘点Spring/Boot的那些常用扩展点( 六 )


在容器启动的过程中,会发布这些事件,如果你需要这容器启动的某个时刻进行什么操作,只需要监听对应的事件即可 。
事件的传播
事件的传播是什么意思呢?
我们都知道,在中有子父容器的概念,而事件的传播就是指当通过子容器发布一个事件之后,不仅可以触发在这个子容器的事件监听器,还可以触发在父容器的这个事件的监听器 。
上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
([] args) {
// 创建一个父容器
text =();
//将 打119监听器 注册到父容器中
text.(ener.class);
text.();
// 创建一个子容器
ext =();
//将 救人监听器 注册到子容器中
ext.(.class);
ext.();
// 设置一下父容器
ext.(text);
// 通过子容器发布着火的事件,触发监听
ext.(("着火了"));
}
}
创建了两个容器,父容器注册了打119的监听器,子容器注册了救人的监听器,然后将子父容器通过关联起来,最后通过子容器,发布了着火的事件 。
运行结果:
1
2
救人
打119
从打印的日志,的确可以看出,虽然是子容器发布了着火的事件,但是父容器的监听器也成功监听了着火事件 。
源码验证
事件传播源码
从这段源码可以看出,如果父容器不为空,就会通过父容器再发布一次事件 。
传播特性的一个坑
前面说过,在容器启动的过程,会发布很多事件,如果你需要有相应的扩展,可以监听这些事件 。但是,在环境下,你的这些发布的事件的监听器可能会执行很多次 。为什么会执行很多次呢?其实就是跟传播特性有关 。
在的环境下,为了使像和这些不同的服务的配置相互隔离,会创建很多的子容器,而这些子容器都有一个公共的父容器,那就是项目启动时创建的容器,事件的监听器都在这个容器中 。而这些为了配置隔离创建的子容器,在容器启动的过程中,也会发布诸如t等这样的事件,如果你监听了这些事件,那么由于传播特性的关系,你的这个事件的监听器就会触发多次 。
如何解决这个坑呢?
你可以进行判断这些监听器有没有执行过,比如加一个判断的标志;或者是监听类似的事件,比如ent事件,这种事件是在启动中发布的事件,而子容器不是,所以不会多次发这种事件,也就会只执行一次 。
事件的运用举例 1、在中的使用
又来以举例了 。。的n监听了,然后判断如果是t就进行相应的处理,这个类还实现了接口 。。
1
2
3
4
5
6
7
8
9
10
11
12
n, ,{
@
( event) {
if( && ) {
// fail-fast -> check allare
this..().mes();
}
}
}
说实话,这监听代码写的不太好,监听了,那么所有的事件都会回调这个类的方法,但是方法实现又是当是t类型才会往下走,那为什么不直接监听t呢?
可以给个差评 。
膨胀了膨胀了 。。
2、在的运用
在的中,当项目启动的时候,会自动往注册中心进行注册,那么是如何实现的呢?当然也是基于事件来的 。当web服务器启动完成之后,就发布事件 。
然后不同的注册中心的实现都只需要监听这个事件,就知道web服务器已经创建好了,那么就可以往注册中心注册服务实例了 。如果你的服务没往注册中心,看看是不是web环境,因为只有web环境才会发这个事件 。