您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

一文掌握Spring事件驱动模型实战

时间:2023-03-10 11:31:18  来源:  作者:热爱生活的阿德哥



今天跟大家介绍一个简单的购物车提交订单的示例代码,如何使用Spring的事件驱动模型来模拟下单流程中扣减商品库存、扣减会员积分抵钱、核销会员优惠券等场景:

JAVACopy code// 自定义事件类
public class OrderSubmittedEvent extends ApplicationEvent {
    private List<OrderItem> orderItems;
    private Member member;
    private Coupon coupon;
    public OrderSubmittedEvent(Object source, List<OrderItem> orderItems, Member member, Coupon coupon) {
        super(source);
        this.orderItems = orderItems;
        this.member = member;
        this.coupon = coupon;
    }
    public List<OrderItem> getOrderItems() {
        return orderItems;
    }
    public Member getMember() {
        return member;
    }
    public Coupon getCoupon() {
        return coupon;
    }
}

// 事件监听器:扣减商品库存
@Component
public class StockEventHandler implements ApplicationListener<OrderSubmittedEvent> {
    @Autowired
    private StockService stockService;
    @Override
    public void onApplicationEvent(OrderSubmittedEvent event) {
        List<OrderItem> orderItems = event.getOrderItems();
        for (OrderItem orderItem : orderItems) {
            stockService.decreaseStock(orderItem.getProductId(), orderItem.getQuantity());
        }
    }
}

// 事件监听器:扣减会员积分抵钱
@Component
public class PointEventHandler implements ApplicationListener<OrderSubmittedEvent> {
    @Autowired
    private PointService pointService;
    @Override
    public void onApplicationEvent(OrderSubmittedEvent event) {
        Member member = event.getMember();
        int totalPoints = 0;
        List<OrderItem> orderItems = event.getOrderItems();
        for (OrderItem orderItem : orderItems) {
            totalPoints += orderItem.getPoints();
        }
        pointService.decreasePoints(member.getId(), totalPoints);
    }
}

// 事件监听器:核销会员优惠券
@Component
public class CouponEventHandler implements ApplicationListener<OrderSubmittedEvent> {
    @Autowired
    private CouponService couponService;
    @Override
    public void onApplicationEvent(OrderSubmittedEvent event) {
        Coupon coupon = event.getCoupon();
        if (coupon != null) {
            couponService.useCoupon(coupon.getId());
        }
    }
}

// 订单服务类
@Service
public class OrderService {
    @Autowired
    private ApplicationContext applicationContext;
    public void submitOrder(List<OrderItem> orderItems, Member member, Coupon coupon) {
        // 创建订单
        Order order = createOrder(orderItems, member, coupon);
        // 发布订单提交事件
        OrderSubmittedEvent orderSubmittedEvent = new OrderSubmittedEvent(this, orderItems, member, coupon);
        applicationContext.publishEvent(orderSubmittedEvent);
    }
    private Order createOrder(List<OrderItem> orderItems, Member member, Coupon coupon) {
        // 创建订单逻辑
    }
}

// 商品库存服务类
@Service
public class StockService {
    public void decreaseStock(Long productId, int quantity) {
        // 扣减商品库存逻辑
    }
}

// 会员积分服务类
@Service
public class PointService {
    public void decreasePoints(Long memberId, int points) {
        // 扣减会员积分逻辑
    }
}

// 会员优惠券服务类
@Service
public class CouponService {
    public void useCoupon(Long couponId) {
        // 核销会员优惠券逻辑
    }
}

在示例代码中,OrderSubmittedEvent类表示订单提交事件,StockEventHandler类表示扣减商品库存的事件监听器,PointEventHandler类表示扣减会员积分抵钱的事件监听器,CouponEventHandler类表示核销会员优惠券的事件监听器,OrderService类表示订单服务类,StockService类表示商品库存服务类,PointService类表示会员积分服务类,CouponService类表示会员优惠券服务类。

当调用OrderService类的submitOrder()方法时,会创建订单并发布订单提交事件,StockEventHandler类、PointEventHandler类和CouponEventHandler类中的onApplicationEvent()方法将被自动调用,从而实现扣减商品库存、扣减会员积分抵钱、核销会员优惠券的操作。

在实际项目中,上述示例代码仅仅是一个简单的示例,实际业务逻辑可能更加复杂,需要根据具体情况进行调整和优化。同时,为了保证事件处理的正确性和稳定性,需要对事件处理方法进行严格的测试和调试。

为了保证事件处理的顺序和可靠性,可以使用Spring框架提供的@Order注解来指定事件监听器的执行顺序。可以在StockEventHandler类上添加@Order注解,指定其执行顺序为1,而在PointEventHandler类上添加@Order注解,指定其执行顺序为2,这样就可以保证扣减商品库存的操作先于扣减会员积分抵钱的操作。

javaCopy code// 事件监听器:扣减商品库存
@Component
@Order(1)
public class StockEventHandler implements ApplicationListener<OrderSubmittedEvent> {
    // ...
}

// 事件监听器:扣减会员积分抵钱
@Component
@Order(2)
public class PointEventHandler implements ApplicationListener<OrderSubmittedEvent> {
    // ...
}

为了方便扩展和管理事件监听器,可以使用Spring框架提供的@EventListener注解来替代ApplicationListener接口。可以在StockEventHandler类中添加@EventListener注解,指定其监听OrderSubmittedEvent事件,而无需实现ApplicationListener接口。

javaCopy code// 事件监听器:扣减商品库存
@Component
public class StockEventHandler {
    @Autowired
    private StockService stockService;
    @EventListener
    public void handleOrderSubmittedEvent(OrderSubmittedEvent event) {
        List<OrderItem> orderItems = event.getOrderItems();
        for (OrderItem orderItem : orderItems) {
            stockService.decreaseStock(orderItem.getProductId(), orderItem.getQuantity());
        }
    }
}

使用Spring的事件驱动模型可以帮助开发人员更加方便地实现应用程序中的事件处理,并且可以应用于许多不同的场景。但是需要注意的是,现如今基本是微服架构,服务多实例部署,如果部署了多个实例,同一个订单事件可能会被多个实例同时接收并处理,从而导致重复操作的问题。为了解决这个问题,可以使用消息队列来实现事件的异步处理。当订单提交事件触发时,可以将事件信息发送到消息队列中,各个实例从消息队列中订阅事件信息,并进行相应的操作。使用消息队列可以实现事件的解耦合和异步处理,从而提高应用程序的可靠性和性能。好的,今天的分享就到这,下期再会!



Tags:Spring   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  Search: Spring  点击:(54)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  Search: Spring  点击:(39)  评论:(0)  加入收藏
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  Search: Spring  点击:(17)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  Search: Spring  点击:(86)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19  Search: Spring  点击:(86)  评论:(0)  加入收藏
Spring Boot2.0深度实践 核心原理拆解+源码分析
Spring Boot2.0深度实践:核心原理拆解与源码分析一、引言Spring Boot是一个基于Java的轻量级框架,它简化了Spring应用程序的创建过程,使得开发者能够快速搭建一个可运行的应用...【详细内容】
2024-01-15  Search: Spring  点击:(95)  评论:(0)  加入收藏
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: Spring  点击:(91)  评论:(0)  加入收藏
Spring Boot 3.0是什么?
Spring Boot 3.0是一款基于Java的开源框架,用于简化Spring应用程序的构建和开发过程。与之前的版本相比,Spring Boot 3.0在多个方面进行了改进和增强,使其更加易用、高效和灵活...【详细内容】
2024-01-11  Search: Spring  点击:(133)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11  Search: Spring  点击:(124)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  Search: Spring  点击:(117)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(0)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(6)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
站内最新
站内热门
站内头条