这里写目录标题

  • 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相关注解和属性详解相关推荐

  1. @Column注解及属性详解

    @Column注解 用来标识实体类中属性与数据表中字段的对应关系 (1)源码: /** Copyright (c) 2008, 2009, 2011 Oracle, Inc. All rights r ...

  2. spring MVC请求处理类注解属性详解

    spring MVC请求处理类注解属性详解

  3. @Column注解属性详解

    目录 导读 是什么? 步骤 总结 导读 Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制.Java 语言中的类.方法.变量.参数和包等都可以被标注.和 ...

  4. php中的文字排版问题,CSS布局中常用的文字排版相关属性详解

    本篇文章给大家带来的内容是关于CSS布局中常用的文字排版相关属性详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. CSS布局中常用的文字排版相关属性详解 一.设定文字字体.颜色.大 ...

  5. css动画相关属性详解

    css动画相关属性详解 文章目录 css动画相关属性详解 什么是CSS动画? 一.@keyframes规则 二.延迟动画-animation-delay 三.设置动画应运行多少次animation-i ...

  6. Unity 之 打包参数 -- Player面板属性详解

    Unity 之 Project Setting -- Player 面板属性详解 前言 一,Player 1.1 属性说明 1.2 效果展示 二,ICON(图标) 2.1 属性说明 2.2 使用示例 ...

  7. form-login属性详解

    form-login属性详解 form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性: login-page 自定义登录页url,默认为/login log ...

  8. 【微信技术-微信小程序】------- 骨架屏(加载流)配置(skeleton-config)及属性详解 (第三篇)

    本篇文章是骨架屏(skeleton)配置及属性详解(第三篇) 第一篇文章:[微信技术-微信小程序]-------骨架屏(加载流) 简单入门(第一篇) 第二篇文章:[微信技术-微信小程序]------- ...

  9. java rollback_Spring中的@Transactional(rollbackFor = Exception.class)属性详解

    序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,这个注解的用法: 异常 如下图所示,我们都 ...

  10. css动画-animation各个属性详解(转)

    CSS3的animation很容易就能实现各种酷炫的动画,虽然看到别人的成果图会觉得很难,但是如果掌握好各种动画属性,做好酷炫吊炸天的动画都不在话下,好,切入正题.  一.动画属性:  动画属性包括: ...

最新文章

  1. nginx+vsftp图片下载java代码上传
  2. 中介者模式(Mediator Pattern)
  3. UVA - 1587 Box
  4. 网络连接异常、网站服务器失去响应_网站常见故障解决办法
  5. 把HttpClient换成IHttpClientFactory之后,放心多了
  6. IntelliJ IDEA 如何知道项目中的模块数据_如何从项目源中选择模块加入当前项目中(添加模块)_如何移除项目中的模块(移除模块/删除模块)
  7. android launcher 字体大小,Android6.0 Launcher3 修改app字体大小
  8. Java多线程_复习(更新中!!)
  9. MATLAB均值滤波
  10. Oracle数据库的ORA-00257故障解决过程(转载)
  11. winform backgroundWorker 用法
  12. UILabel发光字体
  13. 5990. 找出数组中的所有孤独数字
  14. SystemUI 人脸识别解锁后指纹消耗次数并没有清楚
  15. 4ARM-PEG-DA 4Arm-PEG-ACRL 四臂PEG丙烯酸酯
  16. 能力配不上位置,管理只能“累死”
  17. 从数据孪生发展到元宇宙
  18. 电脑亮度无法调节?所有方法都试过了?
  19. python:实现叠加图片(附完整源码)
  20. 如何将Word文档每页转换为图片保存?

热门文章

  1. 如何在家打造一个沉浸式的家庭影院呢?
  2. HTML标记由尖括号和,HTML标记
  3. Unity3D说明文档翻译-Physics Manager
  4. Bluetooth HCI
  5. 计算机怎么取消用户密码,怎么取消电脑开机密码界面
  6. Ubuntu下交叉编译Qt库并移植至ARM板上
  7. Tomb Raider(暴力模拟)
  8. No certificate for team ‘‘ matching ‘iPhone Distribution: VOVA TECH LIMITED ()‘ Select a different s
  9. uniapp上拉加载
  10. Kafka ~ 消息队列之推还是拉