广播服务的顶层接口ApplicationEventPublisher
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
发送消息就是通过publishEvent方法进行发送,具体的实现在AbstractApplicationContext中,
@Override
public void publishEvent(Object event) {
publishEvent(event,null);
}
protected void publishEvent(Object event,@Nullable ResolvableType eventType) {
Assert.notNull(event,"Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent =new PayloadApplicationEvent<>(this, event);
if (eventType ==null) {
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
//此处判断不成立,初始化过程中的registerListeners方法就会把成员变量earlyApplicationEvents设置为空
if (this.earlyApplicationEvents !=null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent !=null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
可以看到广播是通过getApplicationEventMulticaster()方法得到的applicationEventMulticaster这个成员变量来进行的,他是一个ApplicationEventMulticaster接口,最终的multicastEvent调用的是SimpleApplicationEventMulticaster这个实例里的multicastEvent方法,
@Override
public void multicastEvent(final ApplicationEvent event,@Nullable ResolvableType eventType) {
ResolvableType type = (eventType !=null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener listener : getApplicationListeners(event, type)) {
if (executor !=null) {
executor.execute(() -> invokeListener(listener,event));
}
else {
invokeListener(listener, event);
}
}
}
再点进invokeListener看看,
发现最终执行的是ApplicationListener接口的onApplicationEvent方法
自定义广播和监听
现在我们知道了Spring的广播和监听的流程,可以自定义自己的广播和监听器了,首先编写一个自定义事件,
然后自定义自己的广播器,将Spring初始化过程中生成的广播器注入进来,
接着自定义自己的监听器,
最后写一个controller模拟触发,
启动容器,浏览器输入http://localhost:8080/publish,查看打印结果,
至此,Spring的广播和监听基本就结束了,但是,我们可能会有一个小疑问,Spring的事件和监听器是如何绑定的呢?
答案其实是在我们上面看到的广播事件multicastEvent里,
这里,他根据事件和事件类型去获取所有的监听器,点进去看看,
可以发现,Spring是将事件和监听器通过一个并发集合来保存的,将事件类型和来源包装成了一个内部类作为key,监听器集合包装成另一个内部类作为value,在Spring容器初始化的时候会把所有的对应关系都注入到这个集合中