Spring广播与监听

2021-02-23  本文已影响0人  枫林晚_

广播服务的顶层接口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模拟触发,

controller

启动容器,浏览器输入http://localhost:8080/publish,查看打印结果,

结果

至此,Spring的广播和监听基本就结束了,但是,我们可能会有一个小疑问,Spring的事件和监听器是如何绑定的呢?

答案其实是在我们上面看到的广播事件multicastEvent里,

广播事件

这里,他根据事件和事件类型去获取所有的监听器,点进去看看,

获取监听器 绑定事件和监听器的成员变量

可以发现,Spring是将事件和监听器通过一个并发集合来保存的,将事件类型和来源包装成了一个内部类作为key,监听器集合包装成另一个内部类作为value,在Spring容器初始化的时候会把所有的对应关系都注入到这个集合中

上一篇 下一篇

猜你喜欢

热点阅读