ApplicationListener和@EventListener
前言
在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也是设计模式中 发布-订阅模式、观察者模式的一种实现。
观察者模式:简单的来讲就是你在做事情的时候身边有人在盯着你,当你做的某一件事情是旁边观察的人感兴趣的事情的时候,他会根据这个事情做一些其他的事,但是盯着你看的人必须要到你这里来登记,否则你无法通知到他(或者说他没有资格来盯着你做事情)。
对于 Spring 容器的一些事件,可以监听并且触发相应的方法。通常的方法有 2 种,ApplicationListener 接口和**@EventListener** 注解。一个作用在类上,一个作用在方法上。
概念:
要想顺利的创建监听器,并起作用,这个过程中需要这样几个角色:
1、事件(event)可以封装和传递监听器中要处理的参数,如对象或字符串,并作为监听器中监听的目标。
2、监听器(listener)具体根据事件发生的业务处理模块,这里可以接收处理事件中封装的对象或字符串。
3、事件发布者(publisher)事件发生的触发者。
实现ApplicationListener 接口
原生事件
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("事件触发:"+event.getClass().getName());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
@SpringBootApplication
public class ApplicationListenerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ApplicationListenerDemoApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
事件触发:org.springframework.context.event.ContextRefreshedEvent
2021-01-24 22:09:20.113 INFO 9228 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
事件触发:org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
2021-01-24 22:09:20.116 INFO 9228 --- [ main] c.n.ApplicationListenerDemoApplication : Started ApplicationListenerDemoApplication in 1.221 seconds (JVM running for 1.903)
事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
事件触发:org.springframework.boot.context.event.ApplicationReadyEvent
- 1
- 2
- 3
- 4
- 5
- 6
自定义事件
事件
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
监听器
@Component
public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent> {
@Override
public void onApplicationEvent(MyTestEvent event) {
System.out.println("非注解监听器:" + event.getMsg());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
事件发布
@Component
public class MyTestEventPubLisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 事件发布方法
*/
public void pushListener(String msg) {
applicationEventPublisher.publishEvent(new MyTestEvent(this, msg));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
测试:
@RestController
public class TestEventListenerController {
@Autowired
private MyTestEventPubLisher publisher;
@RequestMapping(value = "/test/testPublishEvent1" )
public void testPublishEvent(){
publisher.pushListener("我来了!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
输出:
事件触发:com.njit.personal.unannotation.MyTestEvent
非注解监听器:我来了!
- 1
- 2
@EventListener 注解
原生事件
@Configuration
public class Config {
@EventListener(classes = {ApplicationEvent.class})
public void listen(ApplicationEvent event) {
System.out.println("事件触发:" + event.getClass().getName());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
启动项目:
事件触发:org.springframework.context.event.ContextRefreshedEvent
2021-01-24 22:39:13.647 INFO 16072 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
事件触发:org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
2021-01-24 22:39:13.650 INFO 16072 --- [ main] c.n.ApplicationListenerDemoApplication : Started ApplicationListenerDemoApplication in 1.316 seconds (JVM running for 2.504)
事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
事件触发:org.springframework.boot.context.event.ApplicationReadyEvent
- 1
- 2
- 3
- 4
- 5
- 6
自定义事件
监听器
//事件和发布还是使用上边的
@Component
public class MyAnnotationListener {
@EventListener
public void listener1(MyTestEvent event) {
System.out.println("注解监听器1:" + event.getMsg());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
事件触发:com.njit.personal.unannotation.MyTestEvent
注解监听器1:我来了!
非注解监听器:我来了!
- 1
- 2
- 3
项目常用
@EventListener(AvailabilityChangeEvent.class)
public void init(AvailabilityChangeEvent<ReadinessState> event) {
//项目启动会触发监听器,下面写一些业务逻辑
....
}
- 1
- 2
- 3
- 4
- 5
或者
@Component
public class MyApplicationListener implements ApplicationListener<AvailabilityChangeEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
//项目启动会触发监听器,下面写一些业务逻辑
....
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
参考:
https://segmentfault.com/a/1190000039097608
https://zhuanlan.zhihu.com/p/620722589