关于Spring AOP中切点修饰符@annotation、@args与args约束说明
前言
于其说这是一篇文章,不如说这是一篇笔记,主要介绍了@annotation
、@args
和args
的作用以及一些坑点。这里主要记录一些项目用到的,没有成一套体系,网上其他文章对Spring AOP的切点修饰符可能有比较全的描述。如果以后有遇到其他场景,会在这里补充。
背景
主要是实习公司需要开发一个注解来实现某些特定功能,项目是基于Spring Boot搭建的,因此很容易想到Spring的AOP技术来实现。通过查阅资料和官方文档,发现@annotation
注解可以满足这个需求。同时我也研究了@args
与·args
两个修饰符,讨论一下这两个修饰符到底在干什么。
Spring AOP原理
Spring的AOP使用动态代理模式。在代理模式中有两个对象:代理对象与被代理对象(目标对象),代理模式中是说使用代理对象来操作被代理对象,而动态代理,说明这个代理对象可以根据需要生成,这就是“动”的含义。
关键就在于这个代理对象,我们既然可以在代理对象中调用被代理对象的方法,那么我们就可以在方法执行前、后等做一些操作,这种操作叫做类增强。我们定义方法,写各种各样的表达式,目标就是要匹配正确的方法做类增强。
所以,我们就遇到了第一个坑点:为什么AOP的切点定义不起作用?
大方向有两个原因:
- 切点定义有问题
- Spring为你生成的根本不是代理对象
第二点的排查比较容易,找到你期望增强的方法,然后运行debug模式,观察定义目标方法的对象是不是代理对象:
例如,TestController
就不是代理对象,xServiceImpl
就是代理对象,而且是通过GCLIB进行动态代理的
相关阅读:spring 依赖注入时,什么时候会创建代理类
切点修饰符
@annotation
定义
官方定义:
Limits matching to join points where the subject of the join point (the method being run in Spring AOP) has the given annotation.
也就是说,如果把你定义的注解修饰在某一个方法上,那么就会命中,执行定义的类增强逻辑。
例子
定义一个注解@append
,用于在字符串前后增加一些符号。例如接收到的字符串为hello
,输出*** hello ***
。
- Append注解定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Append {public String word() default "***";
}
- 注解处理器定义
/*** Append的注解处理器*/
@Aspect
@Component
public class AppendProcessor {@Around("@annotation(appendAnnotation)")public String process(ProceedingJoinPoint joinPoint, Append appendAnnotation) throws Throwable{String res = appendAnnotation.word() + " " + joinPoint.proceed() + " " + appendAnnotation.word();return res;}
}
@annotation(…)传入的是注解对象的引用,可以是类型引用
- service方法定义
@Service
public class XServiceImpl {@Appendpublic String foo(String val) {return val;}
}
- controller定义
@Controller
@RestController
public class TestController {@Autowiredprivate XServiceImpl xService;@GetMapping("/hello")public String hello() {return xService.foo("Hello Word!");}}
运行结果(关注控制台):
args族
对于args约束,我的理解是用于限制匹配方法的参数类型。这个参数有两种,一种是针对普通方法的,另外一种是针对注解的
args
官方定义
Limits matching to join points (the execution of methods when using Spring AOP) where the arguments are instances of the given types.
这是针对普通方法的,从定义中可以知道,args
用来限制匹配方法的参数类型。
使用args,可以传递匹配方法的调用参数
例子
与@annotation
那一节中的例子一样,我们修改一下注解处理器
- 注解处理器定义
/*** Append的注解处理器*/
@Aspect
@Component
public class AppendProcessor {@Around("@annotation(appendAnnotation) && args(val)")public String process(ProceedingJoinPoint joinPoint, Append appendAnnotation, String val) throws Throwable{System.out.println(val);String res = appendAnnotation.word() + " " + joinPoint.proceed() + " " + appendAnnotation.word();return res;}
}
运行结果:
同时观察控制台,会发现val的值是调用匹配方法所传递的值,即Hello Word!
如果我把注解处理器中val的类型改成Integer会发生什么呢?
/*** Append的注解处理器*/
@Aspect
@Component
public class AppendProcessor {@Around("@annotation(appendAnnotation) && args(val)")public String process(ProceedingJoinPoint joinPoint, Append appendAnnotation, Integer val) throws Throwable{System.out.println(val);String res = appendAnnotation.word() + " " + joinPoint.proceed() + " " + appendAnnotation.word();return res;}
}
运行结果:
可以发现,方法匹配失败了,因为打了@Append
注解方法的第一个参数是String,而不是Integer
@args
官方定义
Limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given types.
有@
标志的说明跟注解有关,用来描述方法参数的封装类是否有某个注解。这某个注解的作用域要有类
例子
在@annotation
那一节中的例子的基础上,定义一个新的注解@Demo
@Demo
注解定义
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Demo {}
- 新定义一个
YService
,与XService
做区分,YService
上有@Demo
注解
@Service
@Demo
public class YServiceImpl {public void foo() {}
}
- 修改
Xservice
中的foo
方法:
@Service
public class XServiceImpl {@Appendpublic String foo(YServiceImpl yService, String val) {System.out.println("方法开始执行");return val;}
}
- 在注解处理器中新增一个方法
@Around("@annotation(appendAnnotation) && @args(cn.acmsmu.aop.Demo,..)")public String process2(ProceedingJoinPoint joinPoint, Append appendAnnotation) throws Throwable{String res = appendAnnotation.word() + " " + joinPoint.proceed() + " " + appendAnnotation.word();System.out.println(res);return res;}
这里的
@args
表示匹配方法可以有多个参数,第一个参数的类必须被@Demo
注解修饰
运行结果
共同点与区别
- 共同点:都是对目标方法的参数类型进行限制
- 区别:
args
: 单纯针对待增强方法的参数类型,不会关系参数的类@args
: 关注待增强方法参数的类是否被某个注解修饰
关于Spring AOP中切点修饰符@annotation、@args与args约束说明相关推荐
- Spring AOP中定义切点(PointCut)和通知(Advice)
本文讨论一下Spring AOP编程中的两个关键问题,定义切点和定义通知,理解这两个问题能应付大部分AOP场景. 如果你还不熟悉AOP,请先看AOP基本原理,本文的例子也沿用了AOP基本原理中的例子. ...
- Spring AOP 中的切点是什么?如何定义切点?
Spring AOP 中的切点是什么?如何定义切点? 什么是切点? 在 Spring AOP 中,切点(Pointcut)是指一组连接点(Join Point)的集合.连接点是程序执行过程中的某个特定 ...
- Spring AOP中定义切点PointCut详解
1.AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年 ...
- java方法设置切点_java相关:Spring AOP中定义切点的实现方法示例
java相关:Spring AOP中定义切点的实现方法示例 发布于 2020-6-6| 复制链接 摘记: 本文实例讲述了Spring AOP中定义切点的实现方法.分享给大家供大家参考,具体如下:一 配 ...
- Spring AOP中pointcut 切点详解
Spring AOP中pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方 ...
- aspect 方法入参 获取_谈谈Spring AOP中@Aspect的高级用法示例
前言 本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧. 1 切点复合运算 支持在切点定义中加入以下运算符进行复合运算: 运算 ...
- 正确理解Spring AOP中的Around advice
Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...
- Spring :Spring AOP 中的一些术语
1.美图 2.概述 2.1 连接点(Jointpoint) 连接点(Jointpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化.方法执行.方法调用.字段调用或处理异常等等,S ...
- Spring Aop中解析spel表达式,实现更灵活的功能
前言 在Spring Aop中,我们可以拿到拦截方法的参数,如果能结合spel表达式,就能实现更加灵活的功能.典型的实现有Spring的缓存注解: @Cacheable(value = "u ...
最新文章
- 在刚刚结束的ACL 2019上,知识图谱领域都发生了哪些大事?
- css根据文字长度实现宽度自适应
- C语言 socket listen()函数(socket()函数创建的socket(套接字描述符)默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求)
- html状态查询爱站,批量获取爱站数据
- openjdk jvm_Java / JVM是如何构建的? 采用OpenJDK是您的答案!
- jersey客户端_项目学生:带有Jersey的Web服务客户端
- 小程序mpvue图片绘制水印_开发笔记:使用 mpvue 开发斗图小程序
- js模板引擎 之handlebars.js
- 产品要想跑得赢,政策定价来帮您
- 自己动手写Docker系列 -- 5.1实现容器的后台运行
- 做实体行业现在难吗?
- 追赶法求解三对角线性方程组的MATLAB程序
- Javascript第六章世上最全常用RegExp正则表达式及表单验证源码第七课
- 打不开_网站源码安装后打不开?教你解决打不开
- fedora安装java
- ce修改器我的世界服务器,ce修改器怎么修改金钱?ce修改器无限金钱图文教程
- 基于Java的超级玛丽游戏的设计与实现(含源文件)
- Web安全深度剖析第三章读书笔记
- Waymo无人车报告:通往自动驾驶之路
- K-means(K均值原型聚类)
热门文章
- QMessageBox.question报错:TypeError: question(QWidget, str, str, buttons: Union[QMessageBox.StandardBut
- Python的__init__.py文件作用
- 企业如何防范和处理负面舆情危机
- MacType - 美化 Windows 字体的神器!(让字体渲染显示效果比苹果电脑更清晰炫丽)
- 畅游云南、迷恋丽江、爱在泸沽湖
- Transactional注解原理解析
- 【赵强老师】SQL中的子查询
- dxperience 10.1.4 下载 汉化 破解
- 设置双卡不同的来电默认铃声
- 8-异前列腺素检测ELISA试剂盒检测原理实用资料