SpringBoot中@EventListener注解的使⽤
⼀:背景
在开发⼯作中,会遇到⼀种场景,做完某⼀件事情以后,需要⼴播⼀些消息或者通知,告诉其他的模块进⾏⼀些事件处理,⼀般来说,可以⼀个⼀个发送请求去通知,但是有⼀种更好的⽅式,那就是事件监听,事件监听也是设计模式中发布-订阅模式、观察者模式的⼀种实现。
观察者模式:简单的来讲就是你在做事情的时候⾝边有⼈在盯着你,当你做的某⼀件事情是旁边观察的⼈感兴趣的事情的时候,他会根据这个事情做⼀些其他的事,但是盯着你看的⼈必须要到你这⾥来登记,否则你⽆法通知到他(或者说他没有资格来盯着你做事情)。
对于 Spring 容器的⼀些事件,可以监听并且触发相应的⽅法。通常的⽅法有 2 种,ApplicationListener 接⼝和@EventListener 注解。
⼆:简介
springboot框架的作用要想顺利的创建,并起作⽤,这个过程中需要这样⼏个⾓⾊:
1、事件(event)可以封装和传递中要处理的参数,如对象或字符串,并作为中监听的⽬标。
2、(listener)具体根据事件发⽣的业务处理模块,这⾥可以接收处理事件中封装的对象或字符串。
3、事件发布者(publisher)事件发⽣的触发者。
三:ApplicationListener 接⼝
ApplicationListener 接⼝的定义如下:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
它是⼀个泛型接⼝,泛型的类型必须是 ApplicationEvent 及其⼦类,只要实现了这个接⼝,那么当容器有相应的事件触发时,就能触发 onApplicationEvent ⽅法。ApplicationEvent 类的⼦类有很多,Spring 框架⾃带的如下⼏个。
使⽤⽅法很简单,就是实现⼀个 ApplicationListener 接⼝,并且将加⼊到容器中就⾏。
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationStartedEvent> {
// @Override
// public void onApplicationEvent(ApplicationEvent event) {
// System.out.println("事件触发:"+Class().getName());
// }
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("事件触发:"+Class().getName());
}
}
可以看到控制台输出:这样就触发了spring默认的⼀些事件。
事件触发:org.t.event.ApplicationStartedEvent
事件触发:org.t.event.ApplicationReadyEvent
⾃定义事件以及监听
定义事件
⾸先,我们需要定义⼀个时间(MyTestEvent),需要继承Spring的ApplicationEvent
public class MyTestEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private String msg ;
public MyTestEvent(Object source,String msg) {
super(source);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
定义
需要定义⼀下,⾃⼰定义的需要实现ApplicationListener,同时泛型参数要加上⾃⼰要监听的事件Class名,在重写的⽅法onApplicationEvent中,添加⾃⼰的业务处理:
@Component
public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent> {
@Override
public void onApplicationEvent(MyTestEvent event) {
System.out.println("⾮注解:" + Msg());
}
}
事件发布
有了事件,有了事件监听者,那么什么时候触发这个事件呢?每次想让收到事件通知的时候,就可以调⽤⼀下事件发布的操作。⾸先在类⾥⾃动注⼊了ApplicationEventPublisher,这个也就是我们
的ApplicationCOntext,它实现了这个接⼝。
@RestController
@RequestMapping("testEventController")
public class MyTestEventController {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@RequestMapping(value = "/testPublishEvent1" )
public void testPublishEvent(){
applicationEventPublisher.publishEvent(new MyTestEvent(this, "我来了"));
}
}
输出结果如下图所⽰:
⾮注解:我来了
四:@EventListener 注解
简单使⽤
除了通过实现接⼝,还可以使⽤@EventListener 注解,实现对任意的⽅法都能监听事件。
在任意⽅法上标注@EventListener 注解,指定 classes,即需要处理的事件类型,⼀般就是 ApplicationEven 及其⼦类,可以设置多项。
@Configuration
public class Config {
@EventListener(classes = {SpringApplicationEvent.class})
public void listen(SpringApplicationEvent event) {
System.out.println("注解事件触发:" + Class().getName());
}
}
启动项⽬
可以看到控制台和之前的输出是⼀样的:
注解事件触发:org.t.event.ApplicationStartedEvent
注解事件触发:org.t.event.ApplicationReadyEvent
⾃定义事件以及监听
使⽤注解的好处是不⽤每次都去实现ApplicationListener,可以在⼀个class中定义多个⽅法,⽤@EventListener来做⽅法级别的注解。
和上⾯类似,事件以及事件发布不需要改变,只要这样定义即可。
此时,就可以有⼀个发布,两个监听到发布的消息了,⼀个是注解⽅式,⼀个是⾮注解⽅式
结果:
注解----1:我来了
⾮注解:我来了
总结
上⾯介绍了@EventListener的原理,其实上⾯⽅法⾥还有⼀个@TransactionalEventListener注解,其实原理是⼀模⼀样的,只是这个监听者可以选择在事务完成后才会被执⾏,事务执⾏失败就不会被执⾏。
这两个注解的逻辑是⼀模⼀样的,并且@TransactionalEventListener本⾝就被标记有@EventListener,
只是最后⽣成时所⽤的⼯⼚不⼀样⽽已。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论