Spring Event事件通知机制
Spring是基于事件驱动模型的,事件驱动模型也就是我们常说的观察者,或者发布-订阅模型。
Spring 的事件角色的类图如下:
spring中的这些接口和抽象类:
- ApplicationEventPublisherAware:接口,用来发布事件
- ApplicationEvent :抽象类,用来定义事件
- ApplicationListener<E extends ApplicationEvent>:接口,用来监听事件,可以在这里实现自己的处理逻辑。
事件定义
/** * 定义事件 */ public class UserRegisterEvent extends ApplicationEvent { public UserRegisterEvent(String name) { //name即source super(name); } }
事件发布
@Service public class UserService implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } public void register(String name) { System.out.println("用户:" + name + " 已注册!"); applicationEventPublisher.publishEvent(new UserRegisterEvent(name)); } }
为了方便,我们可以单独创建一个发布事件的类。
@Component public class SpringEventHelper implements ApplicationEventPublisherAware { private static ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { if (null == SpringEventHelper.applicationEventPublisher) { SpringEventHelper.applicationEventPublisher = applicationEventPublisher; } } public static void publishEvent(ApplicationEvent event) { SpringEventHelper.applicationEventPublisher.publishEvent(event); } }
这样上面发布事件的代码就改为:
@Service public class UserService { public void register(String name) { System.out.println("用户:" + name + " 已注册!"); SpringEventHelper.publishEvent(new UserRegisterEvent(name)); } }
事件订阅(监听者)
/** * 事件监听者,可以自定义处理逻辑 */ @Component public class EmailHandler implements ApplicationListener<UserRegisterEvent> { @Override public void onApplicationEvent(UserRegisterEvent userRegisterEvent) { System.out.println("邮件服务接到通知,给 " + userRegisterEvent.getSource() + " 发送邮件..."); } }
基于注解的监听@EventListener
@Component public class SmsHandler{ @EventListener public void createSmsEvent(UserRegisterEvent event){ System.out.println("短信服务接到通知,给 " + event.getSource() + " 发送短信..."); } }
异步事件
上面的监听事件都是同步触发的,如果想异步只需要两步:
- 启动类(SpringBoot)或Spring配置类上添加 @EnableAsync注解,开启异步支持。
- 所有事件监听方法上添加 @Async注解
@Component public class SmsHandler{ @Async @EventListener public void createSmsEvent(UserRegisterEvent event){ System.out.println("短信服务接到通知,给 " + event.getSource() + " 发送短信..."); } }
事件传播机制
当我们监听一个事件处理完成时,还需要发布另一个事件,一般我们想到的是调用ApplicationEventPublisher#publishEvent发布事件方法,但Spring提供了另一种更加灵活的新的事件继续传播机制,监听方法返回一个事件,也就是方法的返回值就是一个事件对象。
假设现在有一个唱歌的事件和唱歌的监听
/** * @Description 事件 */ public class UserSingEvent extends ApplicationEvent { public UserSingEvent(String name) { super(name); } } /** * @Description 监听者 */ @Component public class UserSingHandler { @EventListener public void createSingEvent(UserSingEvent event) { System.out.println("接到通知,给 " + event.getSource() + " 唱了一首【一剪梅】..."); } }
则上面发短信的事件订阅者可以改为:
@Component public class SmsHandler{ @EventListener public UserSingEvent createSmsEvent(UserRegisterEvent event){ System.out.println("短信服务接到通知,给 " + event.getSource() + " 发送短信..."); String name = (String) event.getSource(); return new UserSingEvent(name); // 发布另外一个事件 } }
完整示例:创建订单
(1)订单实体类
public class Order { private String orderNo; private String orderStatus; private String goods; private Date createTime; public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public String getOrderStatus() { return orderStatus; } public void setOrderStatus(String orderStatus) { this.orderStatus = orderStatus; } public String getGoods() { return goods; } public void setGoods(String goods) { this.goods = goods; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } }
(2)创建订单的事件定义
public class OrderCreateEvent extends ApplicationEvent { private final Order order; public OrderCreateEvent(Object source, Order order) { super(source); this.order = order; } public Order getOrder() { return order; } }
(3)发布事件
@Service public class OrderService { /** * 订单保存 */ public void save() { Order order = new Order(); order.setOrderNo("1"); order.setGoods("手机"); System.out.println("订单保存成功:" + order.toString()); //发布事件 SpringEventHelper.publishEvent(new OrderCreateEvent(this, order)); } }
(4)事件订阅
@Component public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent> { @Override public void onApplicationEvent(OrderCreateEvent event) { System.out.printf(this.getClass().getName() + " -- ApplicationListener 接口实现,订单号[%s]:,商品[%s]\n", event.getOrder().getOrderNo(), event.getOrder().getGoods()); } }
(5)测试
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringConfig.class}) @WebAppConfiguration //全注解的形式必须添加@WebAppConfiguration注解 public class ContextTest { @Autowired private OrderService orderService; @Test public void test(){ orderService.save(); } }
参考
时刻与技术进步,每天一点滴,日久一大步!!!
本博客只为记录,用于学习,如有冒犯,请私信于我。