用 Spring 事件机制解耦你的业务逻辑!别再 Service 注入套娃了!

307 阅读2分钟

点击上方“程序员蜗牛g”,选择“设为星标”跟蜗牛哥一起,每天进步一点点程序员蜗牛g大厂程序员一枚 跟蜗牛一起 每天进步一点点31篇原创内容**公众号

Spring Boot 提供了天然的事件发布与监听机制,它本质上是观察者设计模式的增强版本。

通过它,我们可以让业务主干专注于自身职责,而将“后续响应”广播给监听者,轻松实现解耦、异步与扩展性。

示例背景:一个典型的耦合式服务调用问题

设想我们在实现订单业务 /com/icoderoad/order/OrderService.java 时,创建订单后需依次完成:

  • 更新库存
  • 增加用户积分
  • 发送邮件
  • 写入日志

你可能写出如下代码:

@Servicepublic class OrderService {    @Autowired private InventoryService inventoryService;    @Autowired private UserService userService;    @Autowired private MailService mailService;    @Autowired private LogService logService;
    public void createOrder(Order order) {        orderRepository.save(order);        System.out.println("订单创建成功:" + order.getId());
        try {            inventoryService.decreaseStock(order.getProductId(), order.getQuantity());            userService.addPoints(order.getUserId(), 100);            mailService.sendMail(order.getUserId(), "订单成功", "感谢购买");            logService.logAction("CREATE_ORDER", order.getId());        } catch (Exception e) {            logger.error("后续操作失败", e);        }    }}

这样做的问题是:

  • 耦合严重:服务间依赖链条过长。
  • 难以扩展:增加任何后续逻辑都需改动主服务。
  • 单一职责被打破:核心逻辑与通知流程混杂。

重构策略:引入事件驱动模型

定义事件 /com/icoderoad/order/event/OrderCreatedEvent.java

package com.icoderoad.order.event;
import com.icoderoad.order.model.Order;import org.springframework.context.ApplicationEvent;
public class OrderCreatedEvent extends ApplicationEvent {    private final Order order;
    public OrderCreatedEvent(Object source, Order order) {        super(source);        this.order = order;    }
    public Order getOrder() {        return order;    }}

改造订单服务 /com/icoderoad/order/OrderService.java

@Servicepublic class OrderService {
    private final ApplicationEventPublisher eventPublisher;
    @Autowired    public OrderService(ApplicationEventPublisher eventPublisher) {        this.eventPublisher = eventPublisher;    }
    public void createOrder(Order order) {        // 核心逻辑:保存订单        orderRepository.save(order);        System.out.println("订单创建成功:" + order.getId());
        // 发布事件        OrderCreatedEvent event = new OrderCreatedEvent(this, order);        eventPublisher.publishEvent(event);        System.out.println("已广播订单创建事件");    }}

监听器实现:模块解耦

每一个服务模块,都独立监听事件,路径结构如下:

/com/icoderoad/inventory/InventoryListener.java/com/icoderoad/user/UserListener.java/com/icoderoad/logging/LogListener.java/com/icoderoad/notification/MailListener.java@Componentpublic class InventoryListener {    @Async    @EventListener    public void onOrderCreated(OrderCreatedEvent event) {        System.out.println("【库存服务】处理订单:" + event.getOrder().getId());    }}@Componentpublic class UserListener {    @EventListener    public void onOrderCreated(OrderCreatedEvent event) {        System.out.println("【用户服务】添加积分:" + event.getOrder().getUserId());    }}@Componentpublic class MailListener {    @EventListener    public void onOrderCreated(OrderCreatedEvent event) {        System.out.println("【邮件服务】发送确认邮件:" + event.getOrder().getUserId());    }}@Componentpublic class LogListener {    @EventListener    public void onOrderCreated(OrderCreatedEvent event) {        System.out.println("【日志服务】记录订单操作日志:" + event.getOrder().getId());    }}

⚠️ 注:若启用 @Async 异步监听器,别忘记在主类上加 @EnableAsync

Spring 实现更接近发布-订阅模型,使用 ApplicationContext 作为事件调度中心,天然具备高扩展性和异步处理能力。

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!