场景描述

在秒杀微服务中,笔者在需要各种校验前端传来的参数后,通过 Redis 加锁限流(切面A)并返回,最后封装订单数据推送到 RabbitMQ 消息队列(切面B)做善后工作。

问题:如何将 切面 A 的数据传递 给切面B 处理呢?

/**
* 添加到秒杀流程
*
* @param killId 秒杀商品缓存键 sessionId_skuId
* @param key 随机码 randomCode
* @param num 数量
* @return {@link R}
*/
@GetMapping("/kill")
public R addToSeckill(
@RequestParam("killId") String killId,
@RequestParam("key") String key,
@RequestParam("num") Integer num) {
// 实现类只是带有两个注解方法,返回 null(因为全部交给切面托管了)
String orderSn = seckillService.kill(killId, key, num);
if (StringUtils.isEmpty(orderSn)) {
return R.error();
}
return R.ok().setData(orderSn);
}

解决方案

通过参数传递数据,通过捕获异常保证业务逻辑(离谱但有用)

// 强制修改参数,通过异常返回正常流程,而通过AOP消息队列处理收尾动作
try {
return pjp.proceed(new Object[]{orderTo, null, null});
} catch (Throwable e) {
return orderSn;
}

注意事项:

  1. 参数一致性:必须伪造和方法签名的数量相等的参数 ⇒ 否则线程会抛出异常 I 就返回了,无法执行 pjp.proceed 原始方法 ⇒ 无法跳转第二个切面

    java.lang.IllegalArgumentException: Expecting 3 arguments to proceed, but was passed 1 arguments

  2. 捕获异常不抛出,直接执行正常业务逻辑 ⇒ 否则线程将吞没异常 II

    cn.miozus.gulimall.common.to.mq.SeckillOrderTo cannot be cast to java.lang.String

3.虽然两个切面都返回了 orderSn ,实际最终只有切面A传递到了控制层和前端, 切面B的返回值成了摆设。

跳转过程

打断点查看两个切面的跳转过程。

切面A:准备跳转第二个切面

切面B:发送消息完成

打印日志,可见场景需求,已经满足了。

2022-03-29 17:32:56.521  INFO 7904 --- [io-25000-exec-8] c.m.g.s.aspect.SeckillRabbitMqAspect     : 快速创建订单:发送消息创建完成: 202203291732444881508738921192005634
2022-03-29 17:33:01.526 INFO 7904 --- [io-25000-exec-8] c.m.g.s.controller.SeckillController : 秒杀创建订单用时:28778
seckill orderSn = 202203291732444881508738921192005634
2022-03-29 17:33:01.527 INFO 7904 --- [nectionFactory5] c.m.g.s.config.RabbitMqSeckillConfig : 消息已发送, params: correlationData:null,ack:true,cause:null

其他方案

最简单的办法,不切了,两个切面耦合在一起。注入和调用方法。

【Spring AOP】暴力打通两个切面之间的通信的更多相关文章

  1. Spring Boot 2.X(八):Spring AOP 实现简单的日志切面

    AOP 1.什么是 AOP ? AOP 的全称为 Aspect Oriented Programming,译为面向切面编程,是通过预编译方式和运行期动态代理实现核心业务逻辑之外的横切行为的统一维护的一 ...

  2. spring aop提供了两种实现方式jdk和cglib

    Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. Sprin ...

  3. Android中两个Activity之间简单通信

    在Android中,一个界面被称为一个activity,在两个界面之间通信,采用的是使用一个中间传话者(即Intent类)的模式,而不是直接通信. 下面演示如何实现两个activity之间的通信. 信 ...

  4. 基于WSAAsyncSelect模型的两台计算机之间的通信

    任务目标 编写Win32程序模拟实现基于WSAAsyncSelect模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递.客户端向服务器端发送"请输出从1到1000内所有 ...

  5. 5.2 spring5源码--spring AOP源码分析二--切面的配置方式

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  6. Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式

    背景: 1)指定切面优先级示例:有的时候需要对一个方法指定多个切面,而这多个切面有时又需要按照不同顺序执行,因此,切面执行优先级别指定功能就变得很实用. 2)重复使用切入点表达式:上一篇文章中,定义前 ...

  7. Spring AOP之使用注解创建切面

    上节中我们已经定义了Performance接口,他是切面中的切点的一个目标对象.那么现在就让我们使用AspectJ注解来定义切面吧. 1.定义切面 下面我们就来定义一场舞台剧中观众的切面类Audien ...

  8. Spring AOP事务管理(使用切面把事务管理起来)

    在<Spring Transaction 分析事务属性(事务的基本概念.配置)>基础上 http://blog.csdn.net/partner4java/article/details/ ...

  9. Spring AOP 在XML中声明切面

    转载地址:http://www.jianshu.com/p/43a0bc21805f 在XML中将一个Java类配置成一个切面: AOP元素 用途 <aop:advisor> 定义AOP通 ...

随机推荐

  1. [LeetCode]35.搜索插入位置(Java)

    原题地址: search-insert-position 题目描述: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 请必须使 ...

  2. git忽略文件提交 .gitignore

    Git 忽略规则 详细的忽略规则可以参考官方英文文档 Git 忽略规则优先级 在 .gitingore 文件中,每一行指定一个忽略规则,Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低) ...

  3. Android蓝牙扫码连接时,防止Activity重启

    集成了一个蓝牙的扫码枪,发现每次连接时,应用的当前Activity会销毁再次创建.调试了下, 没有监听到任何的事件,非常困惑.搜了一阵了解到是Android的一个机制. 某些设备配置可能会在运行时发生 ...

  4. centos安装k8s集群

     准备工作 关闭swap,注释swap分区 swapoff -a 配置内核参数,将桥接的IPv4流量传递到iptables的链 cat > /etc/sysctl.d/k8s.conf < ...

  5. 第六题 Z字走法

    我和答案第一种解法是很相似的  但是时间 和空间都被大部分人击败了. 思路就是用一个标记  为0就竖着走 为1就斜着走 把二维数组填满 我觉得难点在于PHYTON如何创建一个二维数组  而且是不定长的 ...

  6. C# 成员访问修饰符protected internal等

    1.C#4个修饰符的权限修饰符 级别 适用成员 解释public 公开 类及类成员的修饰符 对访问成员没有级别限制private   私有 类成员的修饰符 只能在类的内部访问protected 受保护 ...

  7. vim编辑以及脚本编程练习

    转至:http://www.178linux.com/88128 vim编辑器的使用总结: vim在工作过程当中有三种模式:编辑模式.输入模式.末行模式. 1.编辑模式:即命令模式,键盘操作常被理解为 ...

  8. linux shell脚本批量修改密码,无需交互输入

    转至:https://blog.csdn.net/weixin_34409357/article/details/89833777?utm_medium=distribute.pc_relevant. ...

  9. linux配置vnc server,并用vnc viewer连接server

    做过Linux运维的朋友都知道,我们一般很少直接与服务器接触.都是通过终端来连接处理一些事物. 本人常用的终端有图形界面的是vnc viewer还有命令行界面xshell,当然各有千秋,喜欢使用哪个都 ...

  10. Python:Python2和3不同print汉字方式

    Python3: 可以直接通过print('你好')输出 Python2: 需在开头加#encoding=UTF-8 不过之前输出的时候即使加了开头一行,也是一些混乱的汉字,一看就知道编码错误,后来我 ...