首页 > 编程语言 >[Java] Spring Event 发布-订阅模式:解耦与异步通信的高效实现

[Java] Spring Event 发布-订阅模式:解耦与异步通信的高效实现

时间:2025-01-01 13:52:25浏览次数:1  
标签:订阅 Java Spring public UserRegisteredEvent user Event 事件

  • Spring框架通过发布/订阅模式组件间通信提供了高效且松散耦合的解决方案,提升了系统的灵活性和扩展性。

本文探讨该模式的原理、实现、应用场景及其优势与挑战。

1 发布订阅模式:基本概念

  • 发布-订阅模式,又称为观察者模式Observer Pattern)的一种变体,是一种基于消息传递的设计模式

在这个模式中,主要涉及3个核心角色:发布者(Publisher)、订阅者(Subscriber)和消息代理(Message Broker)。

  • 发布者是消息的产生者,它负责生成特定类型的消息并将其发送到消息代理。

发布者不需要了解有哪些订阅者对其发布的消息感兴趣,它只专注于消息的生成和发布。

  • 订阅者则是对特定类型消息感兴趣的组件,它们向消息代理注册自己感兴趣的消息类型。

当消息代理接收到发布者发送的符合订阅者兴趣的消息时,会将消息转发给对应的订阅者。订阅者可以根据接收到的消息进行相应的业务处理。

  • 消息代理是发布者和订阅者之间的中介,它负责接收发布者的消息,并根据订阅者的注册信息将消息分发给相应的订阅者。

消息代理的存在使得发布者和订阅者之间实现了高度的解耦,它们不需要直接相互引用或通信,只需要与消息代理进行交互即可。

2 Spring框架中发布订阅模式的实现

下面通过发布订阅模式实现一个示例:在用户注册成功后,系统自动发送邮件通知用户。

Step1 定义事件(ApplicationEvent)

  • 定义事件类,事件类通常继承自org.springframework.context.ApplicationEvent

我们可以定义一个UserRegisteredEvent类来表示用户注册成功的事件

public class UserRegisteredEvent extends ApplicationEvent {
 // 这里的User是一个包含用户相关信息的实体类
    private User user;
 
 // source:事件的源对象,用于表明这个事件是由哪个对象触发的
 // 具体作用下面订阅事件中解释
    public UserRegisteredEvent(Object source, User user) {
        super(source);
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}

Step2 发布事件

  • 发布事件的组件需要获取 ApplicationEventPublisher 实例,并通过它来发布事件

在用户注册操作成功完成后,发布用户注册事件

@Service
public class UserRegistrationService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void registerUser(User user) {
        // 执行用户注册逻辑,如保存用户信息到数据库等

        // 注册成功后发布事件
        UserRegisteredEvent event = new UserRegisteredEvent(this, user);
        eventPublisher.publishEvent(event);
    }
}

Step3 订阅事件

方式1 ApplicationListener接口

  • 订阅者可以通过实现org.springframework.context.ApplicationListener接口来订阅特定的事件

  • 发送欢迎邮件的服务可以订阅UserRegisteredEvent事件

@Component
public class WelcomeEmailSender implements ApplicationListener<UserRegisteredEvent> {
    @Override
    public void onApplicationEvent(UserRegisteredEvent event) {
        User user = event.getUser();
        // 发送欢迎邮件给用户的逻辑,如调用邮件发送接口等
        System.out.println("Sending welcome email to " + user.getEmail());
    }
}

方式2 @EventListener注解

  • 除了基于接口的订阅方式,Spring还提供了@EventListener注解来简化订阅者的实现。插播一条:如果你想加入我们,可以点击->程序员交流社区

  • Spring还提供了对异步事件的支持,可以使用@Async注解来实现异步处理,从而避免阻塞事件的发布者

@Component
public class AnotherWelcomeEmailSender {
    @EventListener
    @Async
    public void handleUserRegisteredEvent(UserRegisteredEvent event) {
        User user = event.getUser();
        // 发送欢迎邮件的逻辑
        System.out.println("Another welcome email sent to " + user.getEmail());
    }
}

方式3 事件源Object source的作用

  • 假设有一个Web服务和一个API服务都可能触发UserRegisteredEvent事件,你可以在监听器中根据source进一步区分事件的处理方式
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
    Object source = event.getSource();
    if (source instanceof WebRegistrationService) {
        // 处理通过 Web 注册的用户
    } else if (source instanceof ApiRegistrationService) {
        // 处理通过 API 注册的用户
    }
}

3 应用场景

社交网络平台

用户发布新动态后,动态发布服务触发创建事件。
关注者列表服务订阅并推送该动态给关注者,推荐算法服务也订阅事件,分析内容为潜在用户推荐,扩大传播范围。

电商系统

商品管理系统修改价格后发布价格变动事件,促销活动系统订阅并重新评估促销规则,购物车系统订阅并实时更新商品价格,确保用户看到最新价格。

金融交易系统

用户交易时,交易处理服务发布交易事件,包含金额、类型等信息。
账户余额更新系统订阅并更新余额及交易流水,确保准确性和可追溯性。
风险监控系统也订阅事件,实时评估风险,检测异常交易并触发预警机制。

P 小结

  • Spring的发布-订阅模式通过ApplicationEvent、ApplicationListener和@EventListener等组件,解耦了消息的生产者和消费者,并支持异步通信。

这样可以让不同模块独立处理事件,提升系统的灵活性、可扩展性和响应速度。

X 参考文献

标签:订阅,Java,Spring,public,UserRegisteredEvent,user,Event,事件
From: https://www.cnblogs.com/johnnyzen/p/18645518

相关文章

  • 记忆旅游系统|Java|SSM|VUE| 前后端分离
                  【技术栈】1⃣️:架构:B/S、MVC2⃣️:系统环境:Windowsh/Mac3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7+4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html5⃣️数据库可视化工具:navicat6⃣️服务器:SpringBoot自带apacheto......
  • Java代码实现优先级队列
         最近看了PriorityQueue的源码实现后,我深有感悟,其实本质上就是用了堆的数据结构,我也自己尝试实现了优先级队列的代码,不多说了,代码如下。目录源码实现 测试用例代码源码实现    最近看了PriorityQueue的源码实现后,我深有感悟,其实本质上就是用了堆......
  • Java重要面试名词整理(十七):Nacos
    文章目录架构演化技术选型概念相关核心概念核心功能设计注册中心CP架构分析BASE理论配置中心架构演化我们认为架构发展历史经历了这样一个过程:单体架构——>垂直架构——>SOA面向服务架构——>微服务架构。SOA(Service-OrientedArchitecture),面向服务的架......
  • [2608]基于JAVA的纪念品拍卖智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的纪念品拍卖智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景和意义随着互联网技术的快速发展,电子商务已经成为全球商业活动的重要组成部分。其中,拍卖作为一种特殊的交易方式,在线拍卖系统也逐渐受到......
  • springboot527基于Java企业项目管理系统(论文+源码)_kaic
    摘 要如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统企业项目管理系统信息管理难度大,容错率低,管理人员处理数据费工费时,所以专门为解决这个难题开发了一个企业项......
  • springboot526基于Java的大学生考勤系统的设计与实现(论文+源码)_kaic
    摘  要信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理......
  • Java,Future,Callable和Executor
    系列文章目录Java中Future,Callable和Executor学习入门使用文章目录系列文章目录前言一、Future,Callable和Executor是什么?二、使用示例1.编写获取数组最大值方法2.使用Executor和future总结前言如果需要多线程执行某个任务,又希望分给线程的任务能够按照自己指......
  • Java Agent(二)、Javassist入门
    目录1、前言2、什么是Javassist?2.1、Javassist的特点2.2、应用场景3、快速开始3.1、maven依赖3.2、生成一个class文件3.2.1、具体代码3.2.2、执行结果3.3、修改已有类的方法3.3.1、具体代码3.3.2、执行结果3.3.3、问题踩坑3.4、修改属性值3.4.1、具体代码3......
  • springcloud-gateway
    returnFlux.fromIterable(this.handlerMappings).concatMap(mapping->mapping.getHandler(exchange)).next().switchIfEmpty(createNotFoundError()).flatMap(handler->invokeHandler(exchan......
  • Spring Boot 使用 Redis 实现布隆过滤器,精准过滤 “无效” 请求
    SpringBoot使用Redis实现布隆过滤器,精准过滤“无效”请求在当今高并发的互联网应用场景下,如何高效地对海量数据进行过滤,避免无效请求对系统资源造成浪费,是每一个开发者都需要面对的问题。布隆过滤器(BloomFilter)作为一种空间效率极高的概率型数据结构,为我们提供了出......