@Around踩坑记录

news/2025/1/19 13:32:06/

@Around踩坑记录

先上结论:

如果你在定义切面的时候打算使用环绕通知➕定义注解的方式,那么在进行*@Around*("(@annotation(costTrace))") 类似这样的定义的时候,”costTrace“一定要与你定义切面中入参的参数名字一致,而不是参数类型(你定义的注解名字)一致.

1. 背景

在完善自己暑期实习项目的过程中,发现自己在业务逻辑中花了大量的篇幅去打一些和方法耗时计算相关的日志,于是在优化的过程中,第一步便是利用切面编程的思想将这些计算耗时的日志代码通过切面的方式,悄无声息的侵入,把代码篇幅都留给业务逻辑,而不是这些千篇一律的日志打印。

在这里,我通过传统的 (自定义注解 ➕ spring AOP 切面)的方式进行,以下是我的初始版本⬇️

1.1 引入依赖与定义配置


<dependency> <groupId>org.aspectj</groupId>  <artifactId>aspectjrt</artifactId> 
</dependency>  
<dependency> <groupId>org.aspectj</groupId>  <artifactId>aspectjweaver</artifactId> 
</dependency>

spring的xml配置文件中定义:

<aop:config proxy-target-class="true"/>
<aop:aspectj-autoproxy/>

1.2 自定义注解

/*** @author kaihua* @describe : 被该注解标记,将被进行代价计算与日志打印* @date 2023/7/4*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD })
public @interface CostTrace {String value() default "";}

1.3 定义切面

/*** @author kaihua* @describe* @date 2023/7/4*/
@Aspect
@Component
public class CostTraceAspect {/*** CostTrace 切面* @param joinPoint : 切点* @param costTrace : 方法注解* @return : 返回值*/@Around("(@annotation(CostTrace))")public Object handleJoinPoint(ProceedingJoinPoint joinPoint, CostTrace costTrace) {//1. 获取切入点方法信息MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String className = methodSignature.getDeclaringType().getName();String methodName = methodSignature.getName();String costTraceInformation = costTrace.value();Object[] args = joinPoint.getArgs();String requestStr = JSON.toJSONString(args);//2. 定义方法开始时间long begin = System.currentTimeMillis();Object result = null;try {//3. 执行方法result = joinPoint.proceed(args);//4.1 方法执行完毕之后打印日志LoggerManager.info(String.format("the method %s of class %s execution successful, the input parameters are %s, the total time consumption is %dms, the other information: %s", methodName, className, requestStr, System.currentTimeMillis() - begin, costTraceInformation),"","100");} catch (Throwable e) {e.printStackTrace();//4.2 方法若执行失败打印日志LoggerManager.error(String.format("the method %s of class %s execution error, the input parameters are %s, the other information: %s", methodName, className, requestStr, costTraceInformation),"",e);}return result;}
}

2. 问题的出现

在预发环境部署的过程中出现了如下报错

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dependencyTypeHolder' defined in URL [jar:file:/home/admin/taefileserver/target/taefileserver.war/WEB-INF/lib/ateye-client-2.3.8.jar!/ateye-scene.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAdvisor': Cannot resolve reference to bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' while setting bean property 'transactionAttributeSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Cannot resolve reference to bean 'cursitor-pointcut' while setting bean property 'pointcut'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cursitor-pointcut' defined in class path resource [spring-cursitor.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#1': Cannot resolve reference to bean 'jmonitor-pointcut' while setting bean property 'pointcut'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmonitor-pointcut' defined in class path resource [jmonitor-spring.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut

报错非常长,但是通过控制变量法(通过部署前后的日志变化比较,不推荐,,最笨的方法)以及读取日志内容(推荐,但是有时候难以排查问题)发现,日志中pointcut的字眼,并且报错的本质原因是bean容器初始化失败,那必定是某个bean的定义出现了问题。

结合自己新添加的代码,发现只有自己定义的切面被标注了@Component,便把问题锁定在切面中了,但是这段代码乍一看,并没有什么错误,就是一个非常简单的环绕通知定义。

3. 问题的排查

通过复制日志报错搜索解决方案显然不太可行,后面专门去搜索了@Around配合注解如何去进行定义,终于在廖雪峰老师的网站看到了答案.

👉 https://www.liaoxuefeng.com/wiki/1252599548343744/1310052317134882

请添加图片描述

我又重新尝试修改了自己定义的切面的代码,进行部署,终于成功了!!

但是我这里还是不明白,为什么不能够使用注解类型,非要去使用对应的注解参数名字呢?

在一番搜索和chatGpt battle大战之后,大概搞清楚了原因:

**“在使用 @annotation 拦截注解时,需要获取到该注解的属性值,而注解的属性值是在注解对象中定义的,而不是在注解类型中定义的。因此,在 @annotation 中传入注解对象,可以获取到注解的属性值。”**

4. 解决方法的证实

我将切面的@Around定义分别换为了两个版本,结果都可以部署成功,基本可以证明了这个做法的正确性。

// version 1
@Around("(@annotation(costTrace))")
public Object handleJoinPoint(ProceedingJoinPoint joinPoint, CostTrace costTrace)// version 2
@Around("(@annotation(cos))")
public Object handleJoinPoint(ProceedingJoinPoint joinPoint, CostTrace cos)

5. 小结

虽然这个只是一个非常非常非常小的排查问题案例,但是还是不由得产生非常多的感悟:

“作为一个臭写代码的程序员,我们所谓的学习,只是在学习其他人定义的规则,最典型的就是开发过程中的各种框架,我们在不断的学习别人定下来的规则。虽然这个现实是绝望的,但是我们也要从中有所收获,我们今天了解了这个规则,并不应该仅仅停留于学习到了这个规则,更可贵的是要去尝试去思考规则制定者在制定规则时候的思考”


http://www.ppmy.cn/news/797144.html

相关文章

羊驼再度进化,“长颈鹿版”LongLLaMA 来啦,上下文长度冲向 100K ,性能不减

文 | 小戏、ZenMoore 要说当下制约大模型释放更大规模潜力的桎梏&#xff0c;除了机器幻觉&#xff0c;肯定当属受限的上下文长度&#xff0c;前两天微软的 LongNet 正将 Transformer 的上下文长度扩展到夸张的 10 亿量级&#xff0c;这两天撑起了开源大模型一片天的 LLaMA 家族…

spring10-配置数据元

他的作用是提高我们程序性能的&#xff1a;我们怎么用呢&#xff01;先创建我们数据源对象&#xff1a;创建初始化对象之后&#xff0c;创建数据源对象之后&#xff0c;会给我们一些初始化资源。 使用完后还给他 &#xff0c;这是一种环保的思想。 常见的数据源&#xff1a;底…

爬虫反反爬

目录 为什么要反爬&#xff1f; 经常被反爬的主要人群 常见的反爬策略 通过headers字段来反爬 通过headers中的User-Agent字段来反爬 通过referer字段或者是其他字段来反爬 通过cookie来反爬 通过请求参数来反爬 通过从html静态文件中获取请求数据(github登录数据) 通…

能打开共享打印机但是无法连接

已经打开了共享&#xff0c;看到方电脑共享的打印机&#xff0c;但是无法连接 有说要去除更新的&#xff0c;有说改注册表&#xff0c;重启打印服务的&#xff0c;都试了还是不行 后来发现还是要在windows 管理凭据里面将凭据进行添加进去&#xff0c;或者一开始打开共享的时候…

Windows打印机共享相关问题

1.存在多个副本删除不了&#xff0c;或者打印机有黄色感叹号 可删除此文件夹下的内容 解决方法&#xff1a;删除打印机后&#xff0c;选中一个设备&#xff0c;选择打印机属性&#xff0c;删除副本打印机对应的驱动程序和系统安装包。 2.打印机驱动下载 解决方法&#…

Win10系统更新后共享打印机无法打印

如果共享打印机突然不打印或者连不上 试试把这些win10的补丁卸载重启 卸不掉就更新补丁再卸&#xff0c;多试几次 再不行试试用cmd卸或者注册表改值 网上的办法我都试个遍&#xff0c;终于整好了 最后记得禁止系统更新&#xff08;我上次就忘了&#xff09;!

WIN10系统无法连接共享打印机,0x000000400错误完美解决方法;0x00000709错误完美解决方法

win10&#xff0c;win11强行推送更新的补丁将会导致同一个局域网内共享打印机无法正常使用&#xff0c;添加打印机会报错0x00000040或者0x00000709的问题&#xff0c;有些版本的系统是可以在更新补丁里面卸载&#xff0c;重启一下就可以了。但是有些windows版本没办法卸载更新补…

win10、11共享打印机报错无法连接到打印机

大多数是windows更新补丁导致的&#xff0c;只需运行相应版本的的bat文件就可以解决。 使用方法&#xff1a;将下载好的压缩包解压&#xff0c;并运行bat文件。只要打了2021年10月补丁的电脑都需要运行&#xff0c;不管是服务端还是客户端。比如服务端是xp&#xff08;xp不存在…