Spring Event事件监听

  |   0 评论   |   0 浏览

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执行流程

image-20220718111609418

image-20220718111640596

image-20220718111716357

image-20220718111739372

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 : 开发发送邮件


标题:Spring Event事件监听
作者:llp
地址:https://llinp.cn/articles/2022/07/18/1658155585571.html