@Aspect相关注解和属性详解
这里写目录标题
- expose-proxy和proxy-target-class
- 具体例子
- 新增接口和实现
- 定义aop
- 测试
- 注解介绍
- 指示符
- Aspect通配符
- within
- @within
- **@annotation**
- bean
- **execution**
- this
- target
- @**target**
- args
- @args
- 注意:
- 通知参数
expose-proxy和proxy-target-class
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>
expose-proxy即是否需要将当前的代理对象使用 ThreadLocal 进行保存。
打开expose-proxy是因为若我们要拦截某个接口下的所有方法,但是该接口下的一个方法存在内部调用,此时不开启expose-proxy,对于内部调用的方法是不拦截的。比如:
public void test_1(){ this.test_2();}public void test_2(){}
调用 test_1,此时 test_2 将不会被拦截进行增强,因为调用的是 AOP 代理对象而不是当前对象,而 在 test_1 方法内部使用的是 this 进行调用,所以 test_2 将不会被拦截增强,所以该属性 expose-proxy 就是用来解决这个问题的,即 AOP 代理的获取。
proxy-target-class:是否使用 CGLIB 进行代理。
因为 Spring AOP 的底层技术就是使用的是动态代理,分为 JDK 代理 和 CGLIB 代理,该属性的默认值为 false,表示 AOP 底层默认使用的使用 JDK 代理,当需要代理的类没有实现任何接口的时候才会使用 CGLIB 进行代理,如果想都是用 CGLIB 进行代理,可以把该属性设置为 true 即可。
具体例子
定义需要 aop 拦截的方法,模拟一个 User 的增删改操作
新增接口和实现
public interface IUserService {void add(User user);User query(String name);List<User> qyertAll();void delete(String name);void update(User user);
}
@Service("userServiceImpl")public class UserServiceImpl implements IUserService {@Overridepublic void add(User user) {System.out.println("添加用户成功,user=" + user);}@Overridepublic User query(String name) {System.out.println("根据name查询用户成功");User user = new User(name, 20, 1, 1000, "java");return user;}@Overridepublic List<User> qyertAll() {List<User> users = new ArrayList<>(2);users.add(new User("zhangsan", 20, 1, 1000, "java"));users.add(new User("lisi", 25, 0, 2000, "Python"));System.out.println("查询所有用户成功, users = " + users);return users;}@Overridepublic void delete(String name) {System.out.println("根据name删除用户成功, name = " + name);}@Overridepublic void update(User user) {System.out.println("更新用户成功, user = " + user);}
}
定义aop
下述的方法 before_1() 是对接口的 add() 方法进行 前置增强,即在 add() 方法执行之前执行,
@Component@Aspectpublic class UserAspectj {// 在方法执行之前执行@Before("execution(* main.tsmyk.mybeans.inf.IUserService.add(..))")public void before_1(){System.out.println("log: 在 add 方法之前执行....");}
}
测试
1@RunWith(SpringJUnit4ClassRunner.class)2@ContextConfiguration("/resources/myspring.xml")3public class TestBean {45 @Autowired6 private IUserService userServiceImpl;78 @Test9 public void testAdd() {
10 User user = new User("zhangsan", 20, 1, 1000, "java");
11 userServiceImpl.add(user);
12 }
13}
14// 结果:
15// log: 在 add 方法之前执行....
16// 添加用户成功,user=User{name='zhangsan', age=20, sex=1, money=1000.0, job='java'}
注解介绍
@Aspect:作用是把当前类标识为一个切面供容器读取(必须标注在被spring识别的bean上面,即被@Compoment修饰或在xml配置好的类中)@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行
指示符
Aspect通配符
- ***** 匹配任何数量字符;
- . . 匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
- +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
within
匹配指定类或包(接口不算)下的方法
示例 | 描述 |
---|---|
within(cn.javass…*) | cn.javass包及子包下的任何方法执行 |
within(cn.javass…IPointcutService+) | cn.javass包或所有子包下IPointcutService类型及子类型的任何方法 |
within(@cn.javass…Secure *) | 持有cn.javass…Secure注解的任何类型的任何方法必须是在目标对象上声明这个注解,在接口上声明的对它不起作用 |
@within
配所有持有指定注解类型的方法
示例 | 描述 |
---|---|
@within(cn.javass.spring.chapter6.Secure) | 任何目标对象对应的类型持有Secure注解的类方法; |
@annotation
匹配特定注解的所有方法
示例 | 描述 |
---|---|
@annotation(cn.javass.spring.chapter6.Secure ) | 当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配 |
bean
匹配特定名称的Bean对象的所有方法
示例 | 描述 |
---|---|
bean(*Service) | 匹配所有以Service命名(id或name)结尾的Bean |
execution
匹配符合条件的所有方法
示例 | 描述 |
---|---|
public * *(…) | 任何公共方法的执行 |
* cn.javass…IPointcutService.*() | cn.javass包及所有子包下IPointcutService接口中的任何无参方法 |
* cn.javass….(…) | cn.javass包及所有子包下任何类的任何方法 |
* cn.javass…IPointcutService.() | cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法 |
* (!cn.javass…IPointcutService+) .*(…) | 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法 |
* cn.javass…IPointcutService+.*() | cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法 |
* cn.javass…IPointcut*.test*(java.util.Date) | cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的,如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的; |
* cn.javass…IPointcut*.test*(…) throws IllegalArgumentException,ArrayIndexOutOfBoundsException,cn.javass | 包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常 |
* (cn.javass…IPointcutService+&& java.io.Serializable+).*(…) | 任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法 |
@java.lang.Deprecated * *(…) | 任何持有@java.lang.Deprecated注解的方法 |
@java.lang.Deprecated @cn.javass…Secure* *(…) | 任何持有@java.lang.Deprecated和@cn.javass…Secure注解的方法 |
@(java.lang.Deprecated | cn.javass…Secure) **(…) |
(@cn.javass…Secure*) *(…) | 任何返回值类型持有@cn.javass…Secure的方法 |
(@cn.javass…Secure).*(…) | 任何定义方法的类型持有@cn.javass…Secure的方法 |
**(@cn.javass…Secure() ,@cn.javass…Secure()) | 任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1, @Secure String str1); |
((@ cn.javass…Secure ))或(@ cn.javass…Secure) | 任何带有一个参数的方法,且该参数类型持有@ cn.javass…Secure; |
如public void test(Model model);且Model类上持有@Secure注解 | |
* *(@cn.javass…Secure (@cn.javass…Secure *) ,@ cn.javass…Secure (@cn.javass…Secure *)) | 任何带有两个参数的方法,且这两个参数都被@ cn.javass…Secure标记了;且这两个参数的类型上都持有@ cn.javass…Secure; |
* *(java.util.Map<cn.javass…Model, cn.javass…Model>, …) | 任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass…Model, cn.javass…Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(java.util.HashMap<cn.javass…Model,cn.javass…Model>, …)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配 |
* *(java.util.Collection<@cn.javass…Secure *>) | 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解;如public void test(Collection collection);Model类型上持有@cn.javass…Secure |
* *(java.util.Set<? extends HashMap>) | 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承与HashMap;Spring AOP目前测试不能正常工作 |
* *(java.util.List<? super HashMap>) | 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map);Spring AOP目前测试不能正常工作 |
* (<@cn.javass…Secure *>) | 任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解;Spring AOP目前测试不能正常工作 |
this
使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法
示例 | 描述 |
---|---|
this(cn.javass.spring.chapter6.service.IPointcutService) | 当前AOP对象实现了 IPointcutService接口的任何方法 |
this(cn.javass.spring.chapter6.service.IIntroductionService) | 当前AOP对象实现了 IIntroductionService接口的任何方法 |
target
匹配实现了目标接口的对象的所有方法
示例 | 描述 |
---|---|
target(cn.javass.spring.chapter6.service.IPointcutService) | 当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法 |
target(cn.javass.spring.chapter6.service.IIntroductionService) | 当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法, 不可能是引入接口 |
@target
匹配一个目标对象,这个对象必须有特定的注解
示例 | 描述 |
---|---|
@target (cn.javass.spring.chapter6.Secure) | 任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用 |
args
将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型;如果匹配将把该被通知参数传递给通知方法上同名参数。
示例 | 描述 |
---|---|
args (java.io.Serializable,…) | 任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的 |
@args
匹配带该注解的参数的所有方法
示例 | 描述 |
---|---|
@args (cn.javass.spring.chapter6.Secure) | 任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符; |
注意:
除了execution和bean指示符,都可以使用args这种方式进行参数绑定。
如:
@Before(value="execution(* test(*)) && args(param)", argNames="param") public void before1(String param) {System.out.println("===param:" + param); }
通知参数
JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据
package org.aspectj.lang; import org.aspectj.lang.reflect.SourceLocation; public interface JoinPoint {String toString(); //连接点所在位置的相关信息String toShortString(); //连接点所在位置的简短相关信息String toLongString(); //连接点所在位置的全部相关信息Object getThis(); //返回AOP代理对象Object getTarget(); //返回目标对象Object[] getArgs(); //返回被通知方法参数列表Signature getSignature(); //返回当前连接点签名SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置String getKind(); //连接点类型StaticPart getStaticPart(); //返回连接点静态部分 }
ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法
public interface ProceedingJoinPoint extends JoinPoint {public Object proceed() throws Throwable;public Object proceed(Object[] args) throws Throwable; }
JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等
public interface StaticPart {Signature getSignature(); //返回当前连接点签名String getKind(); //连接点类型int getId(); //唯一标识String toString(); //连接点所在位置的相关信息String toShortString(); //连接点所在位置的简短相关信息String toLongString(); //连接点所在位置的全部相关信息 }
参考1
写的特别好的博客,参考2
参考3
@Aspect相关注解和属性详解相关推荐
- @Column注解及属性详解
@Column注解 用来标识实体类中属性与数据表中字段的对应关系 (1)源码: /** Copyright (c) 2008, 2009, 2011 Oracle, Inc. All rights r ...
- spring MVC请求处理类注解属性详解
spring MVC请求处理类注解属性详解
- @Column注解属性详解
目录 导读 是什么? 步骤 总结 导读 Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制.Java 语言中的类.方法.变量.参数和包等都可以被标注.和 ...
- php中的文字排版问题,CSS布局中常用的文字排版相关属性详解
本篇文章给大家带来的内容是关于CSS布局中常用的文字排版相关属性详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. CSS布局中常用的文字排版相关属性详解 一.设定文字字体.颜色.大 ...
- css动画相关属性详解
css动画相关属性详解 文章目录 css动画相关属性详解 什么是CSS动画? 一.@keyframes规则 二.延迟动画-animation-delay 三.设置动画应运行多少次animation-i ...
- Unity 之 打包参数 -- Player面板属性详解
Unity 之 Project Setting -- Player 面板属性详解 前言 一,Player 1.1 属性说明 1.2 效果展示 二,ICON(图标) 2.1 属性说明 2.2 使用示例 ...
- form-login属性详解
form-login属性详解 form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性: login-page 自定义登录页url,默认为/login log ...
- 【微信技术-微信小程序】------- 骨架屏(加载流)配置(skeleton-config)及属性详解 (第三篇)
本篇文章是骨架屏(skeleton)配置及属性详解(第三篇) 第一篇文章:[微信技术-微信小程序]-------骨架屏(加载流) 简单入门(第一篇) 第二篇文章:[微信技术-微信小程序]------- ...
- java rollback_Spring中的@Transactional(rollbackFor = Exception.class)属性详解
序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,这个注解的用法: 异常 如下图所示,我们都 ...
- css动画-animation各个属性详解(转)
CSS3的animation很容易就能实现各种酷炫的动画,虽然看到别人的成果图会觉得很难,但是如果掌握好各种动画属性,做好酷炫吊炸天的动画都不在话下,好,切入正题. 一.动画属性: 动画属性包括: ...
最新文章
- nginx+vsftp图片下载java代码上传
- 中介者模式(Mediator Pattern)
- UVA - 1587 Box
- 网络连接异常、网站服务器失去响应_网站常见故障解决办法
- 把HttpClient换成IHttpClientFactory之后,放心多了
- IntelliJ IDEA 如何知道项目中的模块数据_如何从项目源中选择模块加入当前项目中(添加模块)_如何移除项目中的模块(移除模块/删除模块)
- android launcher 字体大小,Android6.0 Launcher3 修改app字体大小
- Java多线程_复习(更新中!!)
- MATLAB均值滤波
- Oracle数据库的ORA-00257故障解决过程(转载)
- winform backgroundWorker 用法
- UILabel发光字体
- 5990. 找出数组中的所有孤独数字
- SystemUI 人脸识别解锁后指纹消耗次数并没有清楚
- 4ARM-PEG-DA 4Arm-PEG-ACRL 四臂PEG丙烯酸酯
- 能力配不上位置,管理只能“累死”
- 从数据孪生发展到元宇宙
- 电脑亮度无法调节?所有方法都试过了?
- python:实现叠加图片(附完整源码)
- 如何将Word文档每页转换为图片保存?
热门文章
- 如何在家打造一个沉浸式的家庭影院呢?
- HTML标记由尖括号和,HTML标记
- Unity3D说明文档翻译-Physics Manager
- Bluetooth HCI
- 计算机怎么取消用户密码,怎么取消电脑开机密码界面
- Ubuntu下交叉编译Qt库并移植至ARM板上
- Tomb Raider(暴力模拟)
- No certificate for team ‘‘ matching ‘iPhone Distribution: VOVA TECH LIMITED ()‘ Select a different s
- uniapp上拉加载
- Kafka ~ 消息队列之推还是拉