Spring Event事件监听
Spring Event事件监听
Spring Event(Application Event)其实就是一个观察者设计模式,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean 想观察监听另一个Bean 的行为。在开发中我们经常就会遇到修改一个bean时,同时需要去修改其他得bean。或者说当一个bean得值发生变化时,需要修改另一个bean得业务。还有一些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等。
MQ 确实可以解决这个问题,但 MQ比较重,非必要不提升架构复杂度。因此Spring Event是非常好得选择。
依赖:引入Spring得核心依赖即可
Spring Event同步使用
自定义事件
定义事件,继承 ApplicationEvent 的类成为一个事件类:
@Data
public class OrderProductEvent extends ApplicationEvent {
/** 该类型事件携带的信息 */
private String orderId;
public OrderProductEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
}
定义监听器
监听并处理事件,实现 ApplicationListener 接口或者使用 @EventListener 注解:
/**
* 实现 ApplicationListener 接口,并指定监听的事件类型
*/
@Slf4j
@Component
public class OrderProductListener implements ApplicationListener<OrderProductEvent> {
/**
* 使用 onApplicationEvent 方法对消息进行接收处理
*
* */
@SneakyThrows
@Override
public void onApplicationEvent(OrderProductEvent event) {
String orderId = event.getOrderId();
long start = System.currentTimeMillis();
Thread.sleep(2000);
long end = System.currentTimeMillis();
log.info("{}:校验订单商品价格耗时:({})毫秒", orderId, (end - start));
}
}
定义发布者
发布事件,通过 ApplicationEventPublisher 发布事件:
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
/** 注入ApplicationContext用来发布事件 */
private final ApplicationContext applicationContext;
/**
* 下单
*
* @param orderId 订单ID
*/
public String buyOrder(String orderId) {
long start = System.currentTimeMillis();
// 1.查询订单详情
// 2.检验订单价格 (同步处理)
applicationContext.publishEvent(new OrderProductEvent(this, orderId));
long end = System.currentTimeMillis();
log.info("任务全部完成,总耗时:({})毫秒", end - start);
return "购买成功";
}
}
测试执行
@SpringBootTest
public class OrderServiceTest {
@Autowired
private OrderService orderService;
@Test
public void buyOrderTest() {
orderService.buyOrder("732171109");
}
}
c.l.l.event.OrderProductListener : 732171109:校验订单商品价格耗时:(2001)毫秒
c.llp.llpspringretry.event.OrderService : 任务全部完成,总耗时:(2005)毫秒
Debug执行流程
Spring Event 异步使用
有些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等。
自定义事件
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MsgEvent {
/** 该类型事件携带的信息 */
public String orderId;
}
定义监听器
推荐使用 @EventListener 注解:
@Slf4j
@Component
public class MsgListener {
@Async
@SneakyThrows
@EventListener(MsgEvent.class)
public void sendMsg(MsgEvent event) {
String orderId = event.getOrderId();
long start = System.currentTimeMillis();
log.info("开发发送短信");
log.info("开发发送邮件");
Thread.sleep(4000);
long end = System.currentTimeMillis();
log.info("{}:发送短信、邮件耗时:({})毫秒", orderId, (end - start));
}
}
定义发布者
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
/** 注入ApplicationContext用来发布事件 */
private final ApplicationContext applicationContext;
/**
* 下单
*
* @param orderId 订单ID
*/
public String buyOrder(String orderId) {
long start = System.currentTimeMillis();
// 1.查询订单详情
// 2.检验订单价格 (同步处理)
// applicationContext.publishEvent(new OrderProductEvent(this, orderId));
// 3.短信通知(异步处理) 新开线程执行监听得业务
applicationContext.publishEvent(new MsgEvent(orderId));
long end = System.currentTimeMillis();
log.info("任务全部完成,总耗时:({})毫秒", end - start);
return "购买成功";
}
}
开启异步支持
@EnableAsync开启异步支持
@EnableAsync
@EnableRetry
@SpringBootApplication
public class LlpSpringRetryApplication {
public static void main(String[] args) {
SpringApplication.run(LlpSpringRetryApplication.class, args);
}
}
c.llp.llpspringretry.event.OrderService : 任务全部完成,总耗时:(6)毫秒
c.llp.llpspringretry.event.MsgListener : 开发发送短信
c.llp.llpspringretry.event.MsgListener : 开发发送邮件