SpringBoot如何使⽤@EventListener实现事件监听机制
导语
  我们先回顾下设计模式中的观察者模式,因为事件监听机制可以说是在典型观察者模式基础上的进⼀步抽象和改进。我们可以在JDK或者各种开源框架⽐如Spring中看到它的⾝影,从这个意义上说,事件监听机制也可以看做⼀种对传统观察者模式的具体实现,不同的框架对其实现⽅式会有些许差别。下⾯就来详细看⼀下事件发布监听机制
⽂章⽬录
什么是事件监听机制
  典型的观察者模式将有依赖关系的对象抽象为了观察者和主题两个不同的⾓⾊,多个观察者同时观察⼀个主题,两者只通过抽象接⼝保持松耦合状态,这样双⽅可以相对独⽴的进⾏扩展和变化:⽐如可以很⽅便的增删观察者,修改观察者中的更新逻辑⽽不⽤修改主题中的代码。但是这种解耦进⾏的并不彻底,这具体体现在以下⼏个⽅⾯:
1.抽象主题需要依赖抽象观察者,⽽这种依赖关系完全可以去除。
2.主题需要维护观察者列表,并对外提供动态增删观察者的接⼝,
3.主题状态改变时需要由⾃⼰去通知观察者进⾏更新。
  我们可以把主题(Subject)替换成事件(event),把对特定主题进⾏观察的观察者(Observer)替换成对特定事件进⾏监听的(EventListener),⽽把原有主题中负责维护主题与观察者映射关系以及在⾃⾝状态改变时通知观察者的职责从中抽出,放⼊⼀个新的⾓⾊事件发布器(EventPublisher)中,事件监听模式的轮廓就展现在了我们眼前,如下图所⽰
常见事件监听机制的主要⾓⾊如下
事件及事件源:对应于观察者模式中的主题。事件源发⽣某事件是特定事件被触发的原因。
事件:对应于观察者模式中的观察者。监听特定事件,并在内部定义了事件发⽣后的响应逻辑。
事件发布器:事件的容器,对外提供发布事件和增删事件的接⼝,维护事件和事件之间的映射关系,并在事件发⽣时负责通知相关。
JDK中对事件监听机制的⽀持
  在JDK java.util.EventObject的类,所有的实现⾃定义的事件类型都需要继承并且实现这个类。
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID =5516075349620653480L;
/**
* The object on which the Event initially occurred.
*/
protected transient Object  source;
/**
* Constructs a prototypical Event.
*
* @param    source    The object on which the Event initially occurred.
* @exception  IllegalArgumentException  if source is null.
*/
public EventObject(Object source){
if(source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return  The object on which the Event initially occurred.
*/
public Object getSource(){
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return  A a String representation of this EventObject.
*/
public String toString(){
return getClass().getName()+"[source="+ source +"]";
}
}
  分析源码可以看到在这个类中有⼀个Object source的变量,逻辑上是作为事件发⽣的事件源,在实际的使⽤中可以包含⼀些事件的源信息。既然了事件源,就必须要有事件的监听机制。在JDK中java.util.EventListener表⽰对于JDK封装的事件的监听
/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
  以上就是JDK为我们实现⾃定义事件监听提供的底层⽀持。针对具体业务场景,我们通过扩展java.util.EventObject来⾃定义事件类型,同时通过扩展java.util.EventListener来定义在特定事件发⽣时被触发的事件。当然,不要忘了还要定义⼀个事件发布器来管理事件并提供发布事件的功能。也就是需要⼀个Publisher来发布事件消息。
  下⾯就来分析⼀下Spring是如何实现事件处理的
Spring容器对事件监听机制的⽀持
  Spring容器,具体⽽⾔是ApplicationContext接⼝定义的容器提供了⼀套相对完善的事件发布和监听
框架,其遵循了JDK中的事件监听标准,并使⽤容器来管理相关组件,使得⽤户不⽤关⼼事件发布和监听的具体细节,降低了开发难度也简化了开发流程。下⾯看看对于事件监听机制中的各主要⾓⾊,Spring框架中是如何定义的,以及相关的类体系结构
如何实现基于注解的事件处理机制
事件发布器
public class ResApplyCheckingPublisher {
@Autowired
private ApplicationContext applicationContext;
/**
* ⽤来推送邮件消息
*/
@Async
public void publish(){
ResApplyCheckingEvent event =new ResApplyCheckingEvent();  applicationContext.publishEvent(event);
}
}
事件源
public class ResApplyCheckingEvent extends ResApplyEvent { public ResApplyCheckingEvent(){
super();
}
}
定制化的事件封装
jdk怎么使用
public abstract class ResApplyEvent extends ApplicationEvent {
//定制化的开发最后Object source 传⼊当前对象或者是封装好的对象public ResApplyEvent(Object source){
super(source);
}
}
ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
/** use serialVersionUID from Spring 1.2 for interoperability */
private static final long serialVersionUID =7099057708183571937L;
/** System time when the event happened */
private final long timestamp;
/**
* Create a new ApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source){
super(source);
this.timestamp = System.currentTimeMillis();
}
/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp(){
return this.timestamp;
}
}
事件
  事件监听实现机制有两种⼀种是实现ApplicationListener接⼝,第⼆种就是使⽤注解的⽅式,这⾥使⽤注解的⽅式
//发送给部门负责⼈
@EventListener
public void toSendDeptLeaderEmail(ResApplyCheckingEvent applyCheckEvent){
// 1. 获取到事件信息
// 2. 校验场景信息
return;
}
实现下⾯接⼝定制化的开发,然后将实现类注⼊到容器中,就可以完成对于时间的监听。
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent>extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
注意以上所有的内容都要在容器中进⾏注册
总结
  通过观察者模式的引⼊,实现了Java底层对于事件监听机制的封装,⽽Spring则是对于JDK的事件机制做了进⼀步的封装。后续还会为⼤家分享如何将事件处理机制封装成⼀个邮件场景启动器。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。