• 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]
    ",
                    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

  • 相关阅读:
    MVC是什么?
    Slice Header中的field_pic_flag的含义?
    Slice header 中的frame_num的含义?
    上下文管理器 contextlib
    mixin模式特点
    Flask中路由原理
    使用Docker搭建Django,Nginx,R,Python部署环境
    使用Docker+Jenkins自动构建部署
    Jenkins 关闭和重启
    使用pipenv管理python项目
  • 原文地址:https://www.cnblogs.com/myitnews/p/13302525.html
Copyright © 2020-2023  润新知