概述
Spring 的事件(Application Event) 为Bean与Bean之间的消息通信提供了支持。当一个Bean处理完一个任务之后,希望另外一个Bean知道并能做相应的处理,这时我们就需要让另一个Bean监听当前Bean所发送的事件。
应用场景
在一些业务场景中,如容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进行操作。
注意
spring 的事件需要遵循如下流程
- 1.自定义事件,集成ApplicationEvent。
- 2.自定义事件监听器,实现ApplicationListener。
- 3.使用容器发布事件
代码—基于Spring-Boot2.0
1.自定义事件
将其实例化以后,就是一个事件对象,即一个事件本省,这个类最主要的部分是构造方法,必须调用父类构造,根据事件的不同,请自行定义属性
import org.springframework.context.ApplicationEvent;
/**
* @ClassName DemoEvent
* @Description TODO 自定义事件类,
* 发布一个事件,就是new 一个对象,
* 并传递到applicationContext.publishEvent(ApplicationEvent event)方法中即可
* @Date 2021/1/3 0:25
* @Version 1.0
**/
public class DemoEvent extends ApplicationEvent {
private static final long serialVersionUID=1L;
private String msg;
public DemoEvent(Object source,String msg){
super(source);
this.msg=msg;
}
public String getMsg(){
return this.msg;
}
public void setMsg(String msg){
this.msg=msg;
}
}
2.定义事件监听器
- 事件监听类,必须被spring容器所管理,当扫描到其实现了ApplicationListenner,会被加入到SimpleApplicationEventMulticaster 维护的 Listener 集合中。
- 核心是实现了ApplicationListenner,当事件发布时,则调用ApplicationListenner.onApplicationEvent()这个方法。
- 其中的msgSelf这个属性是作者加的,为了方便后续输出,实际上
System.out.println("接收到了bean-demoPublisher发布的消息"+msg);
这句话后控制台就会输出。
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @ClassName DemoListener
* @Description TODO 实现了ApplicationListener接口,并指定监听事件的类型
* @Date 2021/1/3 0:29
* @Version 1.0
**/
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
private String msgSelf;
/**
* @Description //使用onApplicationEvent对消息进行接收处理
* @Date 0:32 2021/1/3
* @Param [demoEvent]
* @return void
**/
//使用注解@Async支持 这样不仅可以支持通过调用,也支持异步调用,非常的灵活,需要在config类中加入@EnableAsync 才能开启
//@Async
@Override
public void onApplicationEvent(DemoEvent demoEvent) {
String msg=demoEvent.getMsg();
this.msgSelf="接收到:"+msg;
System.out.println("接收到了bean-demoPublisher发布的消息"+msg);
}
public String getMsgSelf() {
return msgSelf;
}
public void setMsgSelf(String msgSelf) {
this.msgSelf = msgSelf;
}
}
3.定义事件发布类
后边的事件发布调用的就是这个类,可以说是一个入口,但其实,在业务中,感觉可以直接调applicationContext.publishEvent(new DemoEvent(this,msg))这个方法,而不是特意写一个发布类来调用,
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @ClassName DemoPublisher
* @Description TODO 事件发布类
* @Date 2021/1/3 0:33
* @Version 1.0
**/
@Component
public class DemoPublisher {
@Autowired
//注入ApplicationContext用来发布事件
ApplicationContext applicationContext;
//使用ApplicationContext的publishEvent方法发布
public void publish(String msg){
applicationContext.publishEvent(new DemoEvent(this,msg));
}
}
4.测试–通过controller调用
直接使用接口做测试,这里写了两个controller,getPublishTest
使用发布类DemoPublisher,另一个则直接使用 context.publishEvent(new DemoEvent(this,msg))
进行调用;
@Resource
DemoPublisher demoPublisher;
@Resource
DemoListener demoListener;
@ApiOperation("用来测试spring事件")
/**
* @Description //TODO 调用demoPublisher发布
* @Date 1:18 2021/1/3
* @Param [msg]
* @return java.lang.String
**/
@GetMapping("/publish")
public String getPublishTest(@RequestParam("msg") String msg){
msg+="---byDemoPublisher";
demoPublisher.publish(msg);
return demoListener.getMsgSelf();
}
/**
* @Author rising3000 Main.Chen
* @Description //TODO 使用controller直接发布
* @Date 1:26 2021/1/3
**/
@Autowired ApplicationContext context;
@GetMapping("/publishByControl")
public String getPublishTest1(@RequestParam("msg") String msg){
msg+="---byController";
context.publishEvent(new DemoEvent(this,msg));
return demoListener.getMsgSelf();
}
5.验证
发布的事件都被listener 事件监听器所监听,并执行了方法,输出一下语句: