事件机制主要由三个部分组成:
- 事件对象
- 事件监听者
- 事件源头
其中它们之间的关系是,监听者会订阅事件源头,事件源头会发布事件对象。Java原生提供了事件机制,主要包含如下内容:
- EventObject,对应事件对象,自定义的事件对象必须继承该类;
- EventListener,对应事件监听者,处理监听到事件后的后续事情;
- 事件源头只需要维护监听者,还有发布事件对象即可;
下面给出一个基本的例子:
public class OneEvent extends EventObject {
private String eventMsg;
public OneEvent(Object source, String eventMsg) {
super(source);
this.eventMsg = eventMsg;
}
public String getEventMsg() {
return eventMsg;
}
}
public class OneEventListener implements EventListener {
public void handleEvent(OneEvent oneEvent){
System.out.println("OneEvent happens, msg is : " + oneEvent.getEventMsg());
}
}
public class OneEventSource {
// 存储订阅者
private Set<OneEventListener> listenerSet = new HashSet<>();
public void addListener(OneEventListener listener){
listenerSet.add(listener);
}
// 发布事件
public void publishEvent(OneEvent event){
for(OneEventListener listener : listenerSet){
listener.handleEvent(event);
}
}
}
public class TestMain {
public static void main(String[] args) {
// 声明一个事件源
OneEventSource oneEventSource = new OneEventSource();
// 声明一个事件监听者
OneEventListener listener = new OneEventListener();
// 事件监听者订阅事件源
oneEventSource.addListener(listener);
// 事件源进行事件的发布
oneEventSource.publishEvent(new OneEvent(oneEventSource, "one-event"));
}
}
既然Java原生提供了事件机制,我们为什么还要使用Spring的事件机制呢?Java原生的事件机制有如下的缺点对开发者不友好:
- 监听者订阅事件需要手动注册,比如
oneEventSource.addListener(listener);
- 事件源发生事件后,需要手动循环遍历所有监听者逐个通知;
在Spring中,完全可以将如上两步进行自动化管理,其主要包含如下内容:
- ApplicationEvent,对应事件对象,继承EventObject;
- ApplicationListener,对应事件监听者,继承EventListener;
- ApplicationEventPublisher,事件发布者,由它来进行事件的publish;
- ApplicationEventPublisherAware,实现该接口的Bean会被Spring进行管理,且其中声明的ApplicationEventPublisher会被Spring自动设置;
下面给一个具体的使用案例:
public class SpringEvent extends ApplicationEvent {
private String eventMsg;
public SpringEvent(Object source, String eventMsg) {
super(source);
this.eventMsg = eventMsg;
}
public String getEventMsg(){
return this.eventMsg;
}
}
SpringEvent和Java原生事件案例中的OneEvent基本一致,只不过继承的父类不同而已。
@Component
public class SpringListener implements ApplicationListener<SpringEvent> {
@Override
public void onApplicationEvent(SpringEvent event) {
System.out.println("SpringEvent happens, msg is : " + event.getEventMsg());
}
}
监听者Listener必须要交给Spring进行管理,所以必须加上注解@Component
,并且实现的接口泛型中带有该监听者需要监听的事件类型,由此,Spring来管理监听者和事件的绑定关系,以及事件发生时,通知所有监听者的工作。
@RestController
@RequestMapping("event")
public class SpringEventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@GetMapping("/publish")
public void publishEvent(String eventMsg){
applicationEventPublisher.publishEvent(new SpringEvent(this,"SpringEvent"));
}
}
最后,我们的事件发布者SpringEventPublisher也必须要交给Spring进行管理,因此加上注@RestController
,同时对外提供Rest接口服务;
同时,发布者需要实现ApplicationEventPublisherAware
接口,目的是让Spring给我们自动设置ApplicationEventPublisher
发布者,我们只需要调用发布方法即可。
启动服务,访问接口localhost:8080/event/publish
就会发现监听者打印了对应的内容。
网友评论