AOP跨模块捕获异常遭CGLIB拦截而继续向上抛出异常

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、BUG详情

1.1 报错信息

 1.2 接口响应信息

1.3 全局异常处理器的定义

二、排查过程

三、解决方案

四、总结


前言

最近,在开发过程中,我遇到一个不易察觉的小bug。这个bug并没有直接给出报错信息,使得排查问题的根源变得困难。我希望通过分享这个经验,帮助大家避免重蹈覆辙,以免浪费不必要的时间和精力。

为了避免类似的困境,我们应当时刻保持警惕,对开发过程中的每一个细节都进行严格的检查。同时,利用调试工具和日志输出等功能,可以帮助我们更快速地定位和解决问题。此外,定期进行代码审查和测试也是非常必要的,这有助于发现潜在的问题并及时解决。


一、BUG详情

1.1 报错信息

如下图所示:

java.lang.reflect.UndeclaredThrowableException: null
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:780) ~[spring-aop-5.3.27.jar:5.3.27]
Caused by: exception.NoAuthorityException: 无权限访问

 1.2 接口响应信息

预期是抛出无权限访问异常,但是没有被aop捕获,被上层UndeclaredThrowableException异常捕获。

1.3 全局异常处理器的定义

如下图所示:

@ExceptionHandler(Exception.class)public <T> R<T> handle(Exception exception) {if (exception instanceof BindException) {// Bind错误特殊处理return R.wrap(() -> {ApiValidationUtil.checkBinding(((BindException) exception).getBindingResult());return null;});}return R.errorAndLog(exception);}

二、排查过程

找到最上面一层报错,发现错误在CglibAopProxy.class中。

附上源码逻辑:

        @Override@Nullablepublic Object proceed() throws Throwable {try {return super.proceed();}catch (RuntimeException ex) {throw ex;}catch (Exception ex) {if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {// Propagate original exception if declared on the target method// (with callers expecting it). Always propagate it for Kotlin code// since checked exceptions do not have to be explicitly declared there.throw ex;}else {// Checked exception thrown in the interceptor but not declared on the// target method signature -> apply an UndeclaredThrowableException,// aligned with standard JDK dynamic proxy behavior.throw new UndeclaredThrowableException(ex);}}}

从源码可以看出咱们最后抛出的异常就是UndeclaredThrowableException异常,所以说if块里面的逻辑是false。

继续深挖ReflectionUtils.declaresException(getMethod(), ex.getClass())方法的逻辑。

附上declaresException方法源码:

public static boolean declaresException(Method method, Class<?> exceptionType) {Assert.notNull(method, "Method must not be null");Class<?>[] declaredExceptions = method.getExceptionTypes();for (Class<?> declaredException : declaredExceptions) {if (declaredException.isAssignableFrom(exceptionType)) {return true;}}return false;}

method就是方法体了,exceptionType就是异常类型了。

method.getExceptionTypes()从controller层读到异常类型存入declaredExceptions中,与传入的exceptionType进行判断。

declaredException.isAssignableFrom(exceptionType)的意思是declaredException是不是exceptionType的父类。只要满足捕获的异常是接口抛出异常的父类就行了。

因为原来的controller层接口是并没有声明异常。

如下所示:

    //原先的接口@Role(400)@Overridepublic R<UserInfoVO> getUserInfo(String loginName) {Assert.notNull(loginName, "请求参数为空");return sysUserInfoService.getUserInfo(loginName);}

所以declaredExceptions是空的,那当然返回的是false。

所以走了else的逻辑,向上抛出throw new UndeclaredThrowableException(ex)。


三、解决方案

在接口方法上声明错误类型(exceptionType)。

如下所示:

    @Role(400)@Overridepublic R<UserInfoVO> getUserInfo(String loginName) throws NoAuthorityException {Assert.notNull(loginName, "请求参数为空");return sysUserInfoService.getUserInfo(loginName);}

这样的话Class<?>[] declaredExceptions = method.getExceptionTypes();可以读到NoAuthorityException 异常,并和拦截到的异常ex.getClass()得到也是NoAuthorityException异常做对比,满足isAssignableFrom方法,所以成功捕获。

由此可见,我们把ex.getClass(),也就是AOP里要捕获的异常设置为Exception也是可以满足需求的。

附一张成功响应图:


四、总结

在本次博客中,我们讨论了AOP跨模块捕获异常时,CGLIB拦截导致异常继续向上抛出的问题。通过分析问题原因和解决方案,我们了解到CGLIB拦截异常是由于代理对象与目标对象继承关系导致的问题。通过使用AspectJ的解决方案,我们可以避免该问题的发生,从而更好地实现AOP功能。

通过分析CGLIB拦截异常的原因和提出解决方案,我们更好地了解了AOP的实现方式和如何解决跨模块异常处理的问题。这对于在实际开发中更好地应用AOP技术具有重要的指导意义。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/216355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据科学工作的20个Pandas函数(备忘)

Pandas 是数据科学社区中使用最广泛的库之一&#xff0c;它是一个强大的工具&#xff0c;可以进行数据操作、清理和分析。 本文将提供最常用的 Pandas 函数以及如何实际使用它们的样例。我们将涵盖从基本数据操作到高级数据分析技术的所有内容&#xff0c;到本文结束时&#xf…

攻防世界题目练习——Web引导模式(五)(持续更新)

题目目录 1. FlatScience2. bug3. Confusion1 1. FlatScience 参考博客&#xff1a; 攻防世界web进阶区FlatScience详解 题目点进去如图&#xff0c;点击链接只能看到一些论文pdf 用dirsearch和御剑扫描出一些隐藏文件&#xff1a; robots.txt: admin.php: login.php: f…

配电站房智慧化改造

随着科技的发展和工业化自动化的不断提高&#xff0c;传统的配电室已经不能满足现代工业的需求。配电站房的智慧化改造可以提高电力系统的运行效率和安全性&#xff0c;依托电易云-智慧电力物联网实现配电房无人值守。以下是配电站房智慧化改造的一些主要方面&#xff1a; 设备…

数据分享 I 全国市级商品房屋销售数据,shp/excel格式,2005-2020年数据

基本信息. 数据名称: 全国市级商品房屋销售数据 数据格式: Shp、excel 数据时间: 2005-2020年 数据几何类型: 面 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1spxse商品房销售额&#xff08;亿元&#xf…

css 表示具有特定类或者其他属性的某种标签类型的元素

需求 通过 css 选择器获取某种标签&#xff08;如&#xff1a;div、input 等&#xff09;具有某个属性&#xff08;如&#xff1a;class、id 等&#xff09;的元素&#xff0c;从而修改其样式。 代码 通过 [标签].[属性] 的方式来获取 <div class"test">&l…

合封芯片开发就找宇凡微,提供合封芯片技术支持与资讯

一、引言 随着科技的迅速发展&#xff0c;芯片在各种电子设备中的地位日益凸显&#xff0c;其中越来越受关注的合封芯片给芯片和pcb厂商带来惊喜 合封芯片是指将多个芯片&#xff08;或其他电子元件&#xff09;封装在一个芯片封装体中的芯片。这种封装方式可以实现多个芯片的…

APP自动化测试工具大全

一、UI自动化测试工具 1. uiautomator2 openatx开源的ui自动化工具&#xff0c;支持Android和iOS。主要面向的编程语言是Python&#xff0c;API设计简洁易用&#xff0c;在开源社区也是很受欢迎。 安装&#xff1a; pip install --upgrade --pre uiautomator2# Or you can …

ArcGIS无法绘制一个或多个图层

背景&#xff1a;在导入一份数据时候&#xff0c;arcmap出现无法绘制一个或多个图层的错误&#xff0c;...点数少于要素所要求的的数量&#xff0c;查阅了半天资料发现是制作数据时候拓扑关系错误造成&#xff0c;现将处理方法详细记录如下&#xff1a; 1.原数据&#xff1a; …

北斗卫星助力消防救援实现精确升级

北斗卫星助力消防救援实现精确升级 在浙江省湖州市&#xff0c;当地消防支队建设了基于北斗系统的“智慧用水”等湖州市“智慧消防”综合信息指挥平台&#xff0c;初步实现了火灾精确预警、精确防范、精确指挥和精确处置。 湖州市“智慧用水系统”通过将北斗系统与地理信息管网…

plf::list原理分析

plf::list是一个比std::list性能要好的另外一种实现&#xff0c;根据作者的性能测试&#xff1a; 293% faster insertion 57% faster erasure 17% faster iteration 77% faster sorting 70% faster reversal 91% faster remove/remove_if 63% faster unique 811% faster clear …

【分享】7-Zip软件如何压缩文件?

7-Zip是一款完全免费的解压缩软件&#xff0c;不仅拥有自己独特的格式&#xff0c;还支持众多主流压缩格式&#xff0c;相比其他解压缩软件&#xff0c;它的压缩率更好&#xff0c;压缩速度更快。今天来分享一下如何使用7-Zip软件来压缩文件。 首先&#xff0c;我们可以到7-Zi…

SpringBoot热部署

SpringBoot热部署 借鉴链接&#x1f517;&#xff1a;SpringBoot中的热部署 添加devtools依赖和pom插件 <!-- devtools 依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId&…

C语言——结构体

一、结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量结构的&#xff0c;每个成员可以是不同类型的变量。 二、结构的声明 struct tag {member-list; }variable-list; 描述一个学生&#xff1a; typedef struct Student {char name[20]; //姓名int age; …

SpringBoot入门及整合

前言 Spring Boot是一个基于Spring框架的快速开发脚手架&#xff0c;它简化了Spring应用的初始化和搭建过程&#xff0c;提供了众多便利的功能和特性并且使用"习惯优于配置"的理念&#xff0c;通过提供默认设置来快速搭建应用&#xff0c;同时也保留了灵活性以进行定…

IntelliJ IDEA创建一个spark的项目

在开始之前&#xff0c;需要说明的是 要跑通基本的wordcount程序&#xff0c;是不需要在windows上安装 hadoop 和spark的&#xff0c;因为idea在跑程序的时候&#xff0c;会按照 pom.xml配置文件&#xff0c;从指定的 repository源&#xff0c;按照properties指定的版本&#x…

系统架构设计师教程(一)绪论

系统架构设计师 1.1 系统架构概述1.1.1 系统架构的定义及发展历程1.1.2 软件架构的常用分类及建模方法1、软件架构常用分类2、系统架构的常用建模方法 1.2 系统架构设计师概述1.3 如何成为一名好的系统架构设计师 1.1 系统架构概述 自1946年第一台计算机诞生以来&#xff0c;计…

LVDS硬件设计

LVDS接口有: 1、四对信号传输差分线&#xff0c;最多传输 4*728bit数据 2、一对时钟。 3、一对差分线有8位&#xff0c;但是最多传输7 bit 的数据。 4、一个LVDS通道只能传输8bit的RGB信号&#xff08;3*8 3 27bit&#xff09;。高于8Bits 就需要两个channel。 5、LVDS的时钟一…

CSS import 规则

导入 “navigation.css” 样式到当前的样式表&#xff1a; import “navigation.css”; /* 使用字符串 / 或者 import url(“navigation.css”); / 使用 url 地址 */ 属性定义及使用说明 CSS import 用于从其他样式表导入样式规则。 import 规则必须在 CSS 文档的头部&#xff…

怎么用qq邮箱发送大视频文件?一分钟解决!

QQ邮箱发送文件时&#xff0c;单个文件的大小不能超过32MB。但是&#xff0c;如果用户发送的邮件包含多个附件&#xff0c;则所有附件的总大小不能超过2GB。所以&#xff0c;下面就向大家介绍这两种不同的文件大小情况如何发送&#xff0c;下面是三种方法具体的操作。 方法一&…

国产服务器网卡和进口芯片服务器网卡性能测试

服务器网卡的主要功能是管理和处理网络流量&#xff0c;要求数据传输稳定、可靠&#xff0c;性能卓越。受前两年缺芯浪潮影响&#xff0c;国产芯片急流勇进&#xff0c;不断取得新突破和新进展&#xff0c;成为工业以太网控制器领域冉冉升起的新星&#xff0c;为用户提供更多选…