不知道怎么解耦业务?Spring Event 了解一下!

Spring Event详解 Spring Event是Spring框架内建的一种发布/订阅(Publish-Subscribe)模式的实现,它允许应用内部不同组件之间通过事件进行通信。当某个特定事件发生时,系统中对这类事件感兴趣的监听器可以接收到通知并执行相应操作。 阅读详情

来源:blog.youkuaiyun.com/csp732171109/article/details/124377254

  • 写在最前

  • Spring Event 同步使用

    • 1.自定义事件

    • 2.定义监听器

    • 3.定义发布者

    • 4.单测执行

  • Spring Event 异步使用

    • 1.自定义事件

    • 2.定义监听器

    • 3.定义发布者

    • 4.单测执行(同步)

    • 5.开启异步

    • 6.单测执行(异步)

a50a5bdc284601d08123a971433f5786.jpeg


写在最前

实际业务开发过程中,业务逻辑可能非常复杂,核心业务 + N个子业务。如果都放到一块儿去做,代码可能会很长,耦合度不断攀升,维护起来也麻烦,甚至头疼。还有一些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等。

MQ 确实可以解决这个问题,但 MQ 重啊,非必要不提升架构复杂度。针对这些问题,我们了解一下 Spring Event。

Spring Event 同步使用

Spring Event(Application Event)其实就是一个观察者设计模式,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean 想观察监听另一个Bean 的行为。

Spring Event 用来解耦业务真的贼好用!

Demo 地址:https://gitee.com/csps/mingyue-springboot-learning

1.自定义事件

定义事件,继承 ApplicationEvent 的类成为一个事件类

import lombok.Data;
import lombok.ToString;
import org.springframework.context.ApplicationEvent;

/**
 * @author Strive
 * @date 2022/4/22 18:00
 * @description
 */
@Data
@ToString
public class OrderProductEvent extends ApplicationEvent {

  /** 该类型事件携带的信息 */
  private String orderId;

  public OrderProductEvent(Object source, String orderId) {
    super(source);
    this.orderId = orderId;
  }
}

2.定义监听器

监听并处理事件,实现 ApplicationListener 接口或者使用 @EventListener 注解

import com.csp.mingyue.event.events.OrderProductEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 实现 ApplicationListener 接口,并指定监听的事件类型
 *
 * @author Strive
 * @date 2022/4/24 09:09
 * @description
 */
@Slf4j
@Component
public class OrderProductListener implements ApplicationListener<OrderProductEvent> {

  /** 使用 onApplicationEvent 方法对消息进行接收处理 */
  @SneakyThrows
  @Override
  public void onApplicationEvent(OrderProductEvent event) {
    String orderId = event.getOrderId();
    long start = System.currentTimeMillis();
    Thread.sleep(2000);
    long end = System.currentTimeMillis();
    log.info("{}:校验订单商品价格耗时:({})毫秒", orderId, (end - start));
  }
}

3.定义发布者

发布事件,通过 ApplicationEventPublisher 发布事件

import com.csp.mingyue.event.events.OrderProductEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

/**
 * @author Strive
 * @date 2022/4/24 09:25
 * @description
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {

  /** 注入ApplicationContext用来发布事件 */
  private final ApplicationContext applicationContext;

  /**
   * 下单
   *
   * @param orderId 订单ID
   */
  public String buyOrder(String orderId) {
    long start = System.currentTimeMillis();
    // 1.查询订单详情

    // 2.检验订单价格 (同步处理)
    applicationContext.publishEvent(new OrderProductEvent(this, orderId));

    // 3.短信通知(异步处理)

    long end = System.currentTimeMillis();
    log.info("任务全部完成,总耗时:({})毫秒", end - start);
    return "购买成功";
  }
}

4.单测执行

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author Strive
 * @date 2022/4/24 09:28
 * @description
 */
@SpringBootTest
public class OrderServiceTest {
  @Autowired private OrderService orderService;

  @Test
  public void buyOrderTest() {
    orderService.buyOrder("732171109");
  }
}

执行结果如下:

2022-04-24 10:13:17.535  INFO 44272 --- [           main] c.c.m.e.listener.OrderProductListener    : 732171109:校验订单商品价格耗时:(2008)毫秒
2022-04-24 10:13:17.536  INFO 44272 --- [           main] c.c.mingyue.event.service.OrderService   : 任务全部完成,总耗时:(2009)毫秒

Spring Event 异步使用

有些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等。

1.自定义事件

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author Strive
 * @date 2022/4/24 10:18
 * @description
 */
@Data
@AllArgsConstructor
public class MsgEvent {

  /** 该类型事件携带的信息 */
  public String orderId;
}

2.定义监听器

推荐使用 @EventListener 注解

import com.csp.mingyue.event.events.MsgEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * @author Strive
 * @date 2022/4/24 10:20
 * @description
 */
@Slf4j
@Component
public class MsgListener {

  @SneakyThrows
  @EventListener(MsgEvent.class)
  public void sendMsg(MsgEvent event) {
    String orderId = event.getOrderId();
    long start = System.currentTimeMillis();
    log.info("开发发送短信");
    log.info("开发发送邮件");
    Thread.sleep(4000);
    long end = System.currentTimeMillis();
    log.info("{}:发送短信、邮件耗时:({})毫秒", orderId, (end - start));
  }
}

3.定义发布者

/**
  * 下单
  *
  * @param orderId 订单ID
  */
public String buyOrder(String orderId) {
    long start = System.currentTimeMillis();
    // 1.查询订单详情

    // 2.检验订单价格 (同步处理)
    applicationContext.publishEvent(new OrderProductEvent(this, orderId));

    // 3.短信通知(异步处理)
    applicationContext.publishEvent(new MsgEvent(orderId));

    long end = System.currentTimeMillis();
    log.info("任务全部完成,总耗时:({})毫秒", end - start);
    return "购买成功";
}

4.单测执行(同步)

@Test
public void buyOrderTest() {
    orderService.buyOrder("732171109");
}

执行结果如下:

2022-04-24 10:24:13.905  INFO 54848 --- [           main] c.c.m.e.listener.OrderProductListener    : 732171109:校验订单商品价格耗时:(2004)毫秒
2022-04-24 10:24:13.906  INFO 54848 --- [           main] c.c.mingyue.event.listener.MsgListener   : 开发发送短信
2022-04-24 10:24:13.907  INFO 54848 --- [           main] c.c.mingyue.event.listener.MsgListener   : 开发发送邮件
2022-04-24 10:24:17.908  INFO 54848 --- [           main] c.c.mingyue.event.listener.MsgListener   : 732171109:发送短信、邮件耗时:(4002)毫秒
2022-04-24 10:24:17.908  INFO 54848 --- [           main] c.c.mingyue.event.service.OrderService   : 任务全部完成,总耗时:(6008)毫秒

5.开启异步

启动类增加 @EnableAsync 注解

@EnableAsync
@SpringBootApplication
public class MingYueSpringbootEventApplication {

  public static void main(String[] args) {
    SpringApplication.run(MingYueSpringbootEventApplication.class, args);
  }
}

Listener 类需要开启异步的方法增加 @Async 注解

@Async
@SneakyThrows
@EventListener(MsgEvent.class)
public void sendMsg(MsgEvent event) {
    String orderId = event.getOrderId();
    long start = System.currentTimeMillis();
    log.info("开发发送短信");
    log.info("开发发送邮件");
    Thread.sleep(4000);
    long end = System.currentTimeMillis();
    log.info("{}:发送短信、邮件耗时:({})毫秒", orderId, (end - start));
}

6.单测执行(异步)

发送短信的线程显示 task-1,主线程结束后(总耗时:(2017)毫秒)控制台停止打印了

2022-04-24 10:30:59.002  INFO 59448 --- [           main] c.c.m.e.listener.OrderProductListener    : 732171109:校验订单商品价格耗时:(2009)毫秒
2022-04-24 10:30:59.009  INFO 59448 --- [           main] c.c.mingyue.event.service.OrderService   : 任务全部完成,总耗时:(2017)毫秒
2022-04-24 10:30:59.028  INFO 59448 --- [         task-1] c.c.mingyue.event.listener.MsgListener   : 开发发送短信
2022-04-24 10:30:59.028  INFO 59448 --- [         task-1] c.c.mingyue.event.listener.MsgListener   : 开发发送邮件

来个“分享、点赞、在看”👇
lock_guard原理解析 一、说明 lock_guard用来包装Mutex,实现Mutex的自动锁定和解锁。能保证锁定过程中逻辑异常也能自动解锁。 二、windows下的源码 template<class _Mutex> class lock_guard<_Mutex> { // specialization for a single mutex public: typedef _Mutex mutex_type; explicit lock_guard(_Mutex& _Mtx) //传的 阅读详情

相关推荐

Spring注解 @EventListener 的介绍与使用示例以及异常处理

将一个方法标记为监听器,用于监听应用程序事件,事件可以是 ApplicationEvent实例,也可以是其他任意的对象。

i余数的博客 1万+

对SpringEvent 最全面的讲解

Spring Event(解耦神器) 是 Spring 框架中的一个事件机制,用于实现应用程序内部的事件传递和处理。通常情况下,当应用程序需要响应某些特定事件时,可以使用 Spring Event 来实现。

SunBigBoy的博客 5075

Spring Event实现业务解耦

从实战角度出发,介绍使用SpringEvent进行解耦,提升代码可扩展性

技术分享 633

Spring Event 事件发布/监听机制 详解并使用

Spring的事件监听(也叫事件驱动)是观察者模式的一种实现,只要是观察者模式,就含有主题(针对该主题的事件),发布者(发布主题或事件),订阅者(监听主题的人)。有三个部分组成,事件(ApplicationEvent)、监听器(ApplicationListener)和事件发布操作。 作用: 使用事件机制我们可以将相互耦合的代码解耦,从而方便功能拓展和调整。 1. 观察者模式简介 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。 比如,当一个对象被修改时,则会自动通知它的依赖

你若为我繁华,我愿成你烟花 2万+

基于MATLAB的基本数字调制解调系统的设计

基于MATLAB的基本数字调制解调系统的设计一、摘要现代通信系统要求通信距离远、通信容量大、传输质量好,作为其关键技术之一的调制解调技术一直是人们研究的一个重要方向。本文以MATLAB为软件平台,充分利用其提供的通信工具箱和信号处理工具箱中的模块,对数字调制解调系统进行Simulink设计仿真,并且进行误差分析。调制与解调是通信系统中十分重要的一个环节,针对不同的信道环境选择不同的调制与解调方式可...

m0_55395440的博客 5550

5分钟搞定!用ZLMediaKit+GB28181搭建低成本外网视频监控(含避坑指南)

本文详细介绍了如何利用开源ZLMediaKit流媒体服务器与国标GB28181协议,快速搭建低成本、可外网访问的企业级视频监控系统。文章提供了从服务端部署、设备配置到外网访问优化的完整实战指南,并重点分享了网络配置、性能调优及常见问题的避坑方案,帮助用户实现高清视频流的稳定推送与多格式播放。

bush的博客 334

业务解耦神器 Spring Event

Spring Event作为Spring框架的一部分,为开发者提供了一种轻量级的事件驱动机制,能够有效地实现应用内的业务解耦。本文将深入探讨Spring Event的优势、实现方法及其在实际项目中的应用。

谷美的互联网练摊记 1248

颠覆性创新的测量框架与跨领域实证分析

颠覆性创新作为科技发展的重要驱动力,其核心在于实现知识体系的范式转换。从技术原理看,这类创新通常具备知识替代、网络重构和跨领域渗透三大特征,通过引用网络分析和文本挖掘等方法可量化评估其影响力。在工程实践中,CD指数、DI指数等测量工具帮助研究者识别具有突破潜力的成果,而深度学习等新兴技术进一步提升了评估精度。当前AI、半导体等领域的热门技术发展表明,模块化架构和产业协同能有效促进颠覆性创新。面对全球范围内创新颠覆性下降的趋势,优化科研评价体系、构建跨学科协作网络成为关键应对策略。

weixin_29735807的博客 323

Spring Event,贼好用的业务解耦神器!

摘要 Spring Event是Spring框架提供的业务解耦神器,通过观察者模式实现事件驱动。文章介绍了同步和异步两种使用方式:同步方式通过继承ApplicationEvent定义事件,实现ApplicationListener接口监听处理;异步方式使用@EventListener注解处理不需要同步完成的业务(如邮件发送)。相比消息队列,Spring Event更轻量,能有效降低代码耦合度,提升可维护性。实际应用示例展示了订单系统中校验价格和发送通知的解耦实现,体现了其简洁高效的特点。

月色真美 风也温柔 684

MIC(Maximal Information Coefficient)最大互信息系数

MIC(Maximal Information Coefficient)最大互信息系数是一种用于衡量两个变量之间相关性的统计量。它扩展了传统的互信息(MI)和条件互信息(CMI)的概念,具有更广泛的应用范围。MIC能够捕获包括功能性和非功能性的广泛的关联,具有普遍性和公平性。普遍性意味着在足够的样本量下,MIC能够捕捉到广泛的相关关系,而不仅仅局限于特定的功能类型;公平性则意味着MIC对不同类型的包含同等噪声的关系给出了相似的分数。需要注意的是,虽然MIC具有很多优点,但它也有一些局限性。

qlkaicx的博客 4606

docker安装fastdfs+nginx配置

docker安装fastdfs+nginx,实现图片或文件的上传与下载

weixin_47325126的博客 2193

Disruptor+Spring的Event解耦业务

Disruptor: 开源的并发框架,能够在无锁的情况下实现网络的Queue并发操作,其他更多详情介绍 本common包封装的Disruptor与Spring的Event事件组合,实现业务在JVM内解耦。 引入disruptor pom依赖: <disruptor.version>3.4.2</disruptor.version> <!-- disrupt...

xiaoll880214的专栏 2426

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

a_zxswer的博客 192

Spring的解耦语法糖Event你还不知道吗?

文章目录前言ApplicationEvent 与 ApplicationListener 应用实现基于注解事件过滤异步事件监听好处及应用场景源码阅读总结 前言 ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的。如果将实现了 ApplicationListener 接口的 bean 部署到容器中,则每次将 ApplicationEvent 发布到ApplicationContext 时,都会通知到该 bean

沸羊羊_ 1459

毕设-MobileNetV4:给YOLOv8装上轻量化“引擎”——通用瓶颈与C2f融合的实战教程

本文介绍了一种将MobileNetV4与YOLOv8结合的目标检测模型轻量化方案。MobileNetV4通过通用瓶颈(UB)结构实现多任务适配,其核心改进包括动态卷积核、注意力机制和多路径特征聚合,显著提升特征提取能力。作者详细阐述了如何在YOLOv8框架中实现MobileNetV4的通用瓶颈模块,包括"膨胀-卷积-注意力-压缩"的流程设计,并构建完整的backbone网络。该方案通过融合MobileNetV4的轻量化优势与YOLOv8的高效检测架构,在移动设备上实现了精度与速度的良好平

FJN110的博客 505

Dify平台隐患url:/console/api/remote-files/upload暴露高危漏洞,配置nginx htpasswd模块认证机制屏蔽解决

内部网络探测: 攻击者可通过SSRF扫描内网服务云元数据访问: 可能访问AWS/Aliyun/腾讯云等元数据服务服务端请求伪造: 以服务器身份发起任意HTTP请求。

CN_Eden 1325

Spring Boot Event 观察者模式,轻松实现业务解耦

定义事件,继承的类成为一个事件类/**00*/@Data@ToString/**该类型事件携带的信息*/}}监听并处理事件,实现接口或者使用注解/***实现ApplicationListener接口,并指定监听的事件类型*09*/@Slf4j@Component/**使用onApplicationEvent方法对消息进行接收处理*/校验订单商品价格耗时({})毫秒",orderId,(end-start));}}...

JavaShark的博客 258

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Spring Event 解耦业务

Spring Event 解耦业务

959 533

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

详解Spring event如何优雅实现系统业务解耦、实现原理及使用注意项

Spring事件(Spring Event)是Spring框架的一项功能,它允许不同组件之间通过**发布-订阅机制**进行解耦的通信。在Spring中,事件是表示应用程序中特定事件的对象,例如**用户注册、订单创建、数据更新**等。当这些事件发生时,可以通知其他组件来执行相应的操作。

weixin_41821642的博客 1626

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Spring Event如何优雅实现系统业务解耦

Spring事件(Spring Event)是Spring框架的一项功能,它允许不同组件之间通过发布-订阅机制进行解耦的通信。在Spring中,事件是表示应用程序中特定事件的对象,例如用户注册、订单创建、数据更新等。当这些事件发生时,可以通知其他组件来执行相应的操作。事件是一个普通的POJO类,用于封装与应用程序状态变化相关的信息。通常情况下,事件类继承自ApplicationEvent抽象类,Spring中提供了一些内置的事件,也可以自定义事件。事件发布者是一个接口,用于发布事件。

m0_37635053的博客 1315

Spring Event + 异步实现业务的解耦(Spring Retry重试)

自定义事件 定义监听器 启动类添加@EnableAsync和@EnableRetry注解 单元测试 执行结果

BUG指挥课堂 908
上一篇: isEmpty 和 isBlank 的用法区别,至少一半的人答不上来...
下一篇: 我们公司使用了 6 年的Spring Boot 项目部署方案!打包 + Shell 脚本部署详解,稳的一批!...
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值