目录
前言
在Spring框架中,事件(Event)是一种实现应用程序不同组件之间解耦和通信的机制。Spring事件模型基于观察者设计模式,允许发布者(publisher)发送事件,而不需要知道哪些订阅者(subscriber)会接收这些事件。
关键知识点:
ApplicationEvent
:这是所有Spring事件的基础类,自定义事件通常会扩展这个类。
ApplicationListener
:任何希望接收特定类型事件的对象都需要实现这个接口。当一个事件被发布时,所有注册为该事件类型的监听器都会被通知。
ApplicationContext
:Spring应用上下文实现了ApplicationEventPublisher接口,可以用来发布事件,当上下文接收到发布事件的请求时,它会将事件传递给所有注册为该事件类型的监听器。
ApplicationEventMulticaster
:这是实际负责将事件广播给所有相关监听器的组件,默认的实现是SimpleApplicationEventMulticaster,但也可以配置其他实现以支持不同的广播策略,如异步处理或按顺序处理。
事件发布
:发布事件通常通过调用ApplicationEventPublisher
的publishEvent
方法完成,该方法接受一个ApplicationEvent
对象作为参数。
事件监听
:要监听事件,需要创建一个类实现ApplicationListener接口,并覆盖其onApplicationEvent方法。在这个方法中,可以处理具体的事件逻辑。
注解驱动的事件监听
:从Spring 4.2开始,可以通过@EventListener注解来简化事件监听器的实现。只需在方法上添加这个注解,并指定要监听的事件类型,Spring就会自动注册这个方法作为监听器。
异步事件处理
:Spring支持异步处理事件,可以通过配置ApplicationEventMulticaster来启用。这通常用于避免长时间运行的事件处理阻塞主线程。
特定类型的事件
:除了基础的ApplicationEvent外,Spring还提供了许多预定义的事件类型,如ContextRefreshedEvent(上下文刷新事件)、ContextStartedEvent(上下文启动事件)、ContextStoppedEvent(上下文停止事件)和ContextClosedEvent(上下文关闭事件)等。
通过使用事件机制,Spring应用程序能够以松散耦合的方式进行通信,使得各组件之间的依赖关系更加灵活,也更容易进行维护和扩展。
文件结构
实现
MainApplication
MainApplication.java
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
common.OrderCreateEvent
OrderCreateEvent.java
package org.example.common;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
/**
* 我们要操作的对象
*/
@Data
public class OrderCreateEvent extends ApplicationEvent {
public Object log;
/**
* @param log 需要传递的参数
* @param source 事件源对象
*/
public OrderCreateEvent(Object source, Object log) {
super(source);
this.log = log;
}
}
common.OrderEvent
OrderEvent.java
package org.example.common;
import lombok.Data;
import org.springframework.context.ApplicationEvent;
/**
* 我们要操作的对象
*/
@Data
public class OrderEvent extends ApplicationEvent {
public Object log;
private Integer status;
private Integer exists = 0;
private Integer async = 0;
/**
* @param log 需要传递的参数
* @param source 事件源对象
*/
public OrderEvent(Object source, Object log) {
super(source);
this.log = log;
}
}
controller.HelloController
HelloController.java
package org.example.controller;
import org.example.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
public class HelloController {
@Autowired
private OrderService orderService;
@PostMapping("/event-publish")
public void eventPublish() {
orderService.submit();
}
@PostMapping("/event-publish2")
public void eventPublish2() {
orderService.submit2();
}
@PostMapping("/event-publish3")
public void eventPublish3() {
orderService.submit3();
}
@PostMapping("/event-publish4")
public void eventPublish4() {
orderService.submit4();
}
}
service.OrderService
OrderService.java
package org.example.service;
import lombok.extern.slf4j.Slf4j;
import org.example.common.OrderCreateEvent;
import org.example.common.OrderEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class OrderService {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 订单提交
*/
public void submit() {
log.info("提交订单前....");
OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this, "创建订单");
// 发布事件
applicationEventPublisher.publishEvent(orderCreateEvent);
log.info("提交订单后....");
}
public void submit2() {
log.info("提交订单前....");
OrderEvent orderEvent = new OrderEvent(this, "提交订单事件2");
orderEvent.setStatus(1);
// 发布事件
applicationEventPublisher.publishEvent(orderEvent);
log.info("提交订单后....");
}
public void submit3() {
log.info("提交订单前....");
OrderEvent orderEvent = new OrderEvent(this, "提交订单事件3");
orderEvent.setStatus(1);
orderEvent.setExists(1);
// 发布事件
applicationEventPublisher.publishEvent(orderEvent);
log.info("提交订单后....");
}
public void submit4() {
log.info("提交订单前....");
OrderEvent orderEvent = new OrderEvent(this, "提交订单事件4");
orderEvent.setAsync(1);
// 发布事件
applicationEventPublisher.publishEvent(orderEvent);
log.info("提交订单后....");
}
}
service.OrderLogService
OrderLogService.java
package org.example.service;
import lombok.extern.slf4j.Slf4j;
import org.example.common.OrderCreateEvent;
import org.example.common.OrderEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;
@Service
@Slf4j
public class OrderLogService {
/**
* 条件事件监听
* @param OrderCreateEvent orderCreateEvent
*/
@EventListener(classes = {OrderCreateEvent.class})
public void listen(OrderCreateEvent orderCreateEvent) {
log.info("事件监听:{}", orderCreateEvent.getLog());
try {
// 验证事件的同步
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 条件事件监听2
* @param OrderEvent event
*/
@EventListener(condition = "#event.status == 1 && #event.exists == 0")
public void listen2(OrderEvent event) {
log.info("事件监听:{}, event.status = {}", event.getLog(), event.getStatus());
try {
// 验证事件的同步
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 条件事件监听3
* @param OrderEvent event
*/
@EventListener(condition = "#event.status == 1 && #event.exists == 1")
public void listen3(OrderEvent event) {
log.info("事件监听:{}, event.status = {}, event.exist = {}", event.getLog(), event.getStatus(), event.getExists());
try {
// 验证事件的同步
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 异步事件监听
* @param event
*/
@Async
@EventListener(condition = "#event.async == 1")
public void listen4(OrderEvent event) {
try {
// 验证事件的异步
Thread.sleep(5000);
log.info("异步事件监听:{}", event.getLog());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果
POST http://localhost:8080/event-publish
POST http://localhost:8080/event-publish2
POST http://localhost:8080/event-publish3
POST http://localhost:8080/event-publish4
总结
事件机制可以将同一个应用系统内互相耦合的代码进行解耦,并且可以将事件与 Spring 事务结合起来,实现我们工作中的一些业务需求。本文结合案例讲述了事件的基本的用法。
参考
https://blog.csdn.net/mu_se_yao_rao/article/details/119610130?ops_request_misc=%257B