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();
    }

}

 参考

https://www.cnblogs.com/wuzhenzhao/p/12859876.html

posted @ 2020-07-14 22:40  codedot  阅读(1135)  评论(0编辑  收藏  举报