• [Java Framework] [Spring] Spring Event / 事件的使用 一: ApplicationEvent


    简介

    Spring Event 主要是为了解耦代码使用, 对于事件弱相关业务可以添加到事件里面执行
    比如: 会员购买会员卡之后会员的状态变更, 发送邮件或者站内信提醒。

    JDK的Util包里抽象了事件驱动,有兴趣的朋友可以自行去看下相关类的定义。Spring事件模型ApplicationEvent是基于JDK里的事件模型,

    🧲[官方文档] Additional Capabilities of the ApplicationContext

    🧲[相关文章] Spring Event / 事件的使用 二: Transactional Event

    方法 / 步骤

    一: 定义事件实体

    • 📄OrderPayEvent.java
    /**
     * Description:
     *
     * @author: YangGC
     */
    public class OrderPayEvent extends ApplicationEvent {
    
        /**
         * 当前订单对象
         * @param source
         */
        private Order order;
    
        public OrderPayEvent(Object source) {
            super(source);
            this.order = (Order) source;
        }
    
        public Order getOrder() {
            return order;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    二: 定义监听器

    定义监听者的方式,Spring提供了两种,一种是接口方式,一种是注解方式。

    2.1: 接口方式

    这里定义了两个监听者,实现泛型接口ApplicationListener类型为我们刚定义的OrderPayedEvent这里加上Order注解,是因为我们有多个监听者,有此业务场景中可能会有顺序的要求!

    • 📄OrderPayedPrinterListener.java
    @Component
    @Order(1)
    public class OrderPayedPrinterListener implements ApplicationListener<OrderPayedEvent> {
    
        @Override
        public void onApplicationEvent(OrderPayedEvent event) {
            System.out.printf("【线程 - %s 】订单成功成功:第一步,打印小票%n", Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 📄OrderPayedSendMessageListener.java
    @Component
    @Order(2)
    public class OrderPayedSendMessageListener implements ApplicationListener<OrderPayedEvent> {
    
        @Override
        public void onApplicationEvent(OrderPayedEvent event) {
            System.out.printf("【线程 - %s 】订单成功成功:第二步,发送通知商品中心添加库存%n", Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.1: 注解方式

    注解方式是不会有排序功能的,如果你有业务有需要排序,那么建议换成接口方式

    @Component
    public class OrderPayListener {
    
        @EventListener(classes = {OrderPayedEvent.class})
        public void sendTips(OrderPayedEvent event) {
            System.out.printf("【线程 - %s 】订单成功成功:发送用户订单支付消息%n", Thread.currentThread().getName());
        }
    
        @EventListener(classes = {OrderPayedEvent.class})
        public void reward(OrderPayedEvent event) {
            System.out.printf("【线程 - %s 】订单成功成功:奖励业务%n", Thread.currentThread().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三: 发送事件

    • 📄 ShoppingMallConsumerApplication.java
    @SpringBootApplication
    public class ShoppingMallConsumerApplication implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(ShoppingMallConsumerApplication.class);
        }
    
        //这里注入 应用上下文,可以注入 applicationEventPublisher
        @Resource
        ApplicationContext context;
    //    @Resource
    //    ApplicationEventPublisher applicationEventPublisher;
        @Override
        public void run(String... args) throws Exception {
            context.publishEvent(new OrderPayEvent(new Order(100L,"酸菜鱼")));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 打印结果
    【线程 - main 】订单成功成功:第一步,打印小票
    【线程 - main 】订单成功成功:第二步,发送通知商品中心添加库存
    
    • 1
    • 2

    异步处理

    ApplicationEvent对异步支持是怎么样的呢?

    只要在启动类上加上@EnableAsync,在监听器类加上@Async

    • 📄 ShoppingMallConsumerApplication.java
    @EnableAsync
    @SpringBootApplication
    public class ShoppingMallConsumerApplication implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(ShoppingMallConsumerApplication.class);
        }
    
        //这里注入 应用上下文,可以注入 applicationEventPublisher
        @Resource
        ApplicationContext context;
    //    @Resource
    //    ApplicationEventPublisher applicationEventPublisher;
        @Override
        public void run(String... args) throws Exception {
            context.publishEvent(new OrderPayEvent(new Order(100L,"酸菜鱼")));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 打印结果
    【线程 - task-2 】订单成功成功:第二步,发送通知商品中心添加库存
    【线程 - task-1 】订单成功成功:第一步,打印小票
    
    • 1
    • 2

    参考资料 & 致谢

    [1] Spring事件,ApplicationEvent在业务中的应用

  • 相关阅读:
    Leetcode 剑指 Offer II 049. 求根节点到叶节点数字之和
    【R语言】混合图:小提琴图+箱线图
    【python学习】函数式编程和高阶函数 map filter reduce lambda表达式 sorted 闭包 装饰器
    基于gis三维可视化的智慧城市行业运用
    docker安装常用软件
    字节一面:go的协程相比线程,轻量在哪?
    【数据结构】纯c语言双向链表
    程序员基础能力系列(2)——vscode快捷键总结
    Vue和React对比
    想知道怎么给图片加贴纸?手把手教你给图片加贴纸
  • 原文地址:https://blog.csdn.net/YangCheney/article/details/126182066