目录
前言
一、事件驱动机制
二、Spring的事件发布机制
三、Spring事件使用实例
四、Spring事件驱动的实现原理
总结:
在设计模式中有一种设计模式叫做观察者设计模式,观察者模式的大致思想是这样的:有两个比较中重要的概念
一个是:被观察的对象(Subject) 一个是观察的对象(Observer)。
当被观察的对象有变更和改动的时候,能够及时的通知给Observer。
大家细品,是不是有点消息队列的味道。是的,没错。消息队列MQ的思想和观察者模式的思想是一样的。Subject的改动可以通过到每一个Observer。
有同学就会问,观察者模式也好,消息队列也好,和我们要提到Spring的事件发布机制有什么关系勒。我的理解是,在分布式的微服务中,子服务与子服务之间的通信可以选择成熟的MQ中间件来做到业务的解耦。但是如果我们要在单个子服务,不同的模块中要做到类似的功能,我们要怎么实现勒。没错就是我们要提到的Spring的事件发布机制。
---------------------------------------------------------------------------------------------------------------------------
在事件驱动中有三个比较重要的组件:
整个流程如下图
EventPublisher发布一个事件。携带Event对象。
所有监听这个Event的监听器到这个事件,并获取到这个Event对象,进行业务处理。
在Spring框架中,预留了三个接口:分别对应上面事件发布机制的三种抽象对象
分别是
我们可以去查看ApplicationContext的源代码,ApplicationContext是已经实现了ApplicationEventPublisher接口,所有任意一个ApplicationContext的实现类都可以去发布事件。
我们通过一段代码来简单介绍Spring事件驱动的使用
public class EmailEvent extends ApplicationEvent{
…
}
public class SpringTest {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//创建一个ApplicationEvent对象
EmailEvent event = new EmailEvent(…);
//主动触发该事件
context.publishEvent(event);
}
}
public class EmailNotifier implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
//监听EmailEvent事件
if (event instanceof EmailEvent) {
//处理EmailEvent事件
EmailEvent emailEvent = (EmailEvent)event;
…
} else {
…
}
}
}
当事件发布后,在Spring的框架中就会通知所有该事件的监听器,并执行监听器的onApplication方法,并传入发布的Event对象。这样解除了事件发布和事件监听之间的耦合。
当前在Spring框架的设计中也使用一些事件驱动的事件。
比如:ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent 等事件,会在 Spring 容器的生命周期处于启动、停止以及关闭阶段自动触发。如果我们对这些事件感兴趣,就可以直接实现 ApplicationListener 接口,从而对具体某一个事件进行响应。
除了上面通过显示的通过实现ApplicationListener我们也可以通过注解的方式来使用事件监听
@Component
public class TestApplicationListener
@EventListener(classes={ EmailEvent.class})
public void listen(EmailEvent emailEvent){
System.out.println(contextStoppedEvent);
}
}
了解到现在,我们可以猜测下Spring是如何实现事件发布与监听。
我们不妨想想这样的问题:
1、ApplicationEventPubliser是如何获取到对应的监听器。因为在事件发布后,需要获取到对应的事件监听器对象ApplicationListener并执行对应onApplication对象
2、初始化时机,listener对象是在时候初始化的。
首先我们先开始思考第二个问题,说到初始化,我们比较容易联想到Spring容器的启动。
没错,在Spring容器启动的时候就会去注册所有的监听器。
public void refresh() throws BeansException, IllegalStateException {
try {
...
// 初始化自定义事件广播器
initApplicationEventMulticaster();
// 执行刷新
onRefresh();
// 注册监听器
registerListeners();
...
}
}
注册的监听器,是存放在ApplicationEventMulticaster事件多播器里面。
在事件发布时候。publier对象通过获取到ApplicationEventMulticaster对象的getApplicationListener()获取监听器,然后执行对应的multicastEvent方法执行监听器的onApplicationEvent方法
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener listener : getApplicationListeners(event)) {
//获取线程执行器
Executor executor = getTaskExecutor();
if (executor != null) {
//执行监听线程
executor.execute(new Runnable() {
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
listener.onApplicationEvent(event);
}
}
}
设计模式(五)观察者模式_刘望舒的博客-CSDN博客_观察者模式