Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!


Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!

文章插图
一、前言ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的 。如果将实现了 ApplicationListener 接口的 bean 部署到容器中,则每次将 ApplicationEvent 发布到ApplicationContext 时,都会通知到该 bean , 这简直是典型的观察者模式 。设计的初衷就是为了系统业务逻辑之间的解耦 , 提高可扩展性以及可维护性 。
Spring 中提供了以下的事件:
Spring Event 业务解耦神器,大大提高可扩展性,刷爆了!

文章插图
 
二、ApplicationEvent 与 ApplicationListener 应用1.实现自定义事件类,基于 ApplicationEvent 实现扩展:
public class DemoEvent extends ApplicationEvent {private static final long serialVersionUID = -2753705718295396328L;private String msg;public DemoEvent(Object source, String msg) {super(source);this.msg = msg;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}定义 Listener 类,实现 ApplicationListener接口,并且注入到 IOC 中 。等发布者发布事件时 , 都会通知到这个bean,从而达到监听的效果 。
@Componentpublic class DemoListener implements ApplicationListener<DemoEvent> {@Overridepublic void onApplicationEvent(DemoEvent demoEvent) {String msg = demoEvent.getMsg();System.out.println("bean-listener 收到了 publisher 发布的消息: " + msg);}}要发布上述自定义的 event,需要调用 ApplicationEventPublisher 的 publishEvent 方法,我们可以定义一个实现 ApplicationEventPublisherAware 的类,并注入 IOC来进行调用:
@Componentpublic class DemoPublisher implements ApplicationEventPublisherAware {private ApplicationEventPublisher applicationEventPublisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}public void sendMsg(String msg) {applicationEventPublisher.publishEvent(new DemoEvent(this, msg));}}客户端调用 publisher:
@RestController@RequestMapping("/event")public class DemoClient implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}@GetMapping("/publish")public void publish(){DemoPublisher bean = applicationContext.getBean(DemoPublisher.class);bean.sendMsg("发布者发送消息......");}}输出结果:
 
bean-listener 收到了 publisher 发布的消息: 发布者发送消息......
 
2.基于注解我们可以不用实现 AppplicationListener 接口 ,在方法上使用 @EventListener 注册事件 。如果你的方法应该侦听多个事件,并不使用任何参数来定义,可以在 @EventListener 注解上指定多个事件 。
重写 DemoListener 类如下:
public class DemoListener {@EventListener(value = https://www.isolves.com/it/cxkf/kj/2023-11-21/{DemoEvent.class, TestEvent.class})public void processApplicationEvent(DemoEvent event) {String msg = event.getMsg();System.out.println("bean-listener 收到了 publisher 发布的消息: " + msg);}}3.事件过滤如果希望通过一定的条件对事件进行过滤,可以使用 @EventListener 的 condition 属性 。以下实例中只有 event 的 msg 属性是 my-event 时才会进行调用 。
@EventListener(value = https://www.isolves.com/it/cxkf/kj/2023-11-21/{DemoEvent.class, TestEvent.class}, condition = "#event.msg == 'my-event'")public void processApplicationEvent(DemoEvent event) {String msg = event.getMsg();System.out.println("bean-listener 收到了 publisher 发布的消息: " + msg); }此时,发送符合条件的消息,listener 才会侦听到 publisher 发布的消息 。
 
bean-listener 收到了 publisher 发布的消息: my-event
 
4.异步事件监听前面提到的都是同步处理事件,那如果我们希望某个特定的侦听器异步去处理事件,如何做?
使用 @Async 注解可以实现类内方法的异步调用,这样方法在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成 , 即可继续其他的操作 。
@EventListener@Asyncpublic void processApplicationEvent(DemoEvent event) {String msg = event.getMsg();System.out.println("bean-listener 收到了 publisher 发布的消息: " + msg);}使用异步监听时,有两点需要注意: