事件、监听器在我们开发中会经常遇到,比如某个业务逻辑后需要通知另一个组件去执行相应的逻辑,那就可以使用事件和监听,具体的场景:服务 A 在处理完某个逻辑之后,需要通知服务 B 去处理另一个逻辑,或者服务 A 处理完某个逻辑之后,需要将数据同步到微服务 B。
这种场景就可以自定义事件以及监听器来监听,一旦监听到微服务 A 中的某事件发生,就去通知微服务 B 处理对应的逻辑。
一、spring中的事件监听
Spring 通过 ApplicationEvent 类和 ApplicationListener 接口提供 ApplicationContext 中的事件处理。如果将实现 ApplicationListener 接口的 bean 部署到上下文中,则每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。
简单来说主要分为以下几个部分:
- 注册事件
- 注册监听器
- 发布事件
二、spring中事件监听的使用
事件类:(继承ApplicationEvent即可)
@ToString
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(Object source, String message) {
super(source);
this.message = message;
}
}
监听类:(实现ApplicationListener 或者 使用@EventListener注解)
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
Console.log("实现ApplicationListener接口监听到的事件信息:{}", event);
}
}
或
public class MyAnnotationListener {
@EventListener
public void onApplicationEvent(MyEvent event) {
Console.log("@EventListener注解监听到的事件信息:{}", event);
}
}
以bean的方式注入Spring容器:
@Configuration
public class EventConfig {
@Bean
public MyListener getMyListener(){
return new MyListener();
}
@Bean
public MyAnnotationListener getMyAnnotationListener(){
return new MyAnnotationListener();
}
}
测试:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EventConfig.class);
context.refresh();
MyEvent myEvent = new MyEvent(context, "我是事件!");
context.publishEvent(myEvent);
}
}
@EventListener注解监听到的事件信息:MyEvent(message=我是事件!)
实现ApplicationListener接口监听到的事件信息:MyEvent(message=我是事件!)
可以看到,在接口调用发布事件时,监听器就会做出相应的操作。且两种监听器都能监测到同一事件。
三、案例
@ToString
@Setter
@Getter
@AllArgsConstructor
public class Goods {
private String name;
private String price;
}
@Getter
public class MyEvent extends ApplicationEvent {
private Goods goods;
public MyEvent(Object source, Goods goods) {
super(source);
this.goods = goods;
}
}
@Component
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
Goods goods = event.getGoods();
Console.log("商品信息:{}", goods);
}
}
@Service
public class GoodsService {
@Resource
private ApplicationContext applicationContext;
/**
* 发布事件
* @return
*/
public Goods getGoods() {
Goods goods = new Goods("电视", "6666");
MyEvent event = new MyEvent(this, goods);
applicationContext.publishEvent(event);
return goods;
}
}
@RestController
public class EventController {
@Autowired
GoodsService goodsService;
@GetMapping("/user")
public Goods getUser(HttpServletRequest request){
ServletContext application = request.getServletContext();
Goods goods = goodsService.getGoods();
return goods;
}
}
商品信息:Goods(name=电视, price=6666)
四、Spring框架中有哪些不同类型的事件?
除了上面介绍的通过扩展ApplicationEvent 类来开发自定义事件,Spring 还提供了以下5种标准的事件:
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个HTTP请求(Request)结束时触发该事件。