前言
有这么个场景,用户下订单,下单成功需要短信通知用户。
当然第一想到的是通过 MQ 消息队列来实现,但是 MQ 比较重,需要引入新的中间件。
可以采用 SpringBoot 自带的一种消息通知实现方式
Spring Event(Application Event)其实就是一个观察者设计模式,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean 想观察监听另一个Bean 的行为。
两种实现方式
继承 ApplicationEvent 类
定义一个 Event,继承 ApplicationEvent
@Getter
public class DemoEvent extends ApplicationEvent {
private String orderId;
/**
* Create a new {@code ApplicationEvent}.
*
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
public DemoEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
}
定义一个 listener,实现 ApplicationListener
@Component
@Slf4j
public class DemoListener implements ApplicationListener<DemoEvent> {
// @Resource
// private MsgService msgService;
@SneakyThrows
@Override
public void onApplicationEvent(DemoEvent event) {
String orderId = event.getOrderId();
long start = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2);
long end = System.currentTimeMillis();
// String send = msgService.send("订单" + orderId + "下单成功");
// log.info("消息发送:{}", send);
log.info("订单{}耗时:{}ms", orderId, (end - start));
}
}
事件发布
@Slf4j
@Service
public class DemoService {
@Autowired
private ApplicationContext context;
public String buy(String orderId) {
long start = System.currentTimeMillis();
context.publishEvent(new DemoEvent(this, orderId));
long end = System.currentTimeMillis();
log.info("任务完成{}耗时:{}ms", orderId, (end - start));
return "购买成功";
}
}
注解方式
定义一个 Event
@Data
@AllArgsConstructor
public class MsgEvent {
private String msg;
}
定义监听器
使用 @EventListener 注解
@Component
@Slf4j
public class MsgListener {
// @Async
@SneakyThrows
@EventListener(MsgEvent.class)
public void sendMsg(MsgEvent event) {
String orderId = event.getMsg();
long start = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2);
long end = System.currentTimeMillis();
log.info("订单{}耗时:{}ms", orderId, (end - start));
}
}
事件发布
@Slf4j
@Service
public class MsgService {
@Autowired
private ApplicationContext context;
public String send(String msg) {
long start = System.currentTimeMillis();
context.publishEvent(new MsgEvent(msg));
long end = System.currentTimeMillis();
log.info("任务完成{}耗时:{}ms", msg, (end - start));
return "发送成功";
}
}
可以采用异步方式,只需要在 listener 方法上添加 @Async 注解
@Component
@Slf4j
public class MsgListener {
@Async
@SneakyThrows
@EventListener(MsgEvent.class)
public void sendMsg(MsgEvent event) {
String orderId = event.getMsg();
long start = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2);
long end = System.currentTimeMillis();
log.info("订单{}耗时:{}ms", orderId, (end - start));
}
}
同时,启动类开启异步注解
@SpringBootApplication
@EnableAsync
public class EventDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EventDemoApplication.class, args);
}
}