文章目录

  • 概述
  • args()
  • @args()
  • 实例
    • args()
    • @args()

概述

args函数的入参是类名, 而 @args()的入参必须是注解类的类名。

虽然args()允许在类名后使用“+”通配符,但该通配符在此处没有意义,添加和不添加的效果都一样。

args()

该函数接收一个类名,表示目标类方法入参对象是指定类(包含子类)时,切点匹配。

比如args(com.xgj.Waiter) 表示运行时入参是Waiter类型的方法,它和execution(* *(com.xgj.Waiter))的区别在于后者是这对类方法的签名而言的,而前者是针对运行时的入参类型而言。

比如args(com.xgj.Waiter)既匹配addWiter(Waiter waiter),又匹配addNaiveWaiter(NaiveWaiter waiter); 而 execution(* *(com.xgj.Waiter)),实际上 args(com.xgj.Waiter)等价于 execution(* *(com.xgj.Waiter+)),当然也等价于 args(com.xgj.Waiter+)


@args()

该函数接收一个注解类的类名,当方法的运行时入参对象标注了指定的注解时,匹配切点。

我们来通过下图@args(M)匹配示意图来详细解释下:

T0、T1、T2、T3有如上继承关系,假设目标类方法的签名为fun(T1 t),它的入参为T1,而切面的切点定义为@args(M), T2类标注了@M。 当fun(T1 t)的传入对象为T2或者T3时,方法匹配@args(M)声明所定义的切点。

假设方法签名是funt(T1 t),入参为T1,而标注了@M的类是T0,当fun(T1 t)传入T1、T2、T3的实例时,均不匹配切点@args(M).

在类的继承树中,(1)处为方法签名中入参类型在继承树的位置,称之为入参类型点, 而(2)处标注了@M注解的类在类继承树中的位置,称之为注解点。 判断方法在运行时是否匹配@args(M)切点,可以根据(1)和(2)在类继承树中的相对位置来判断。

  • 如果在继承树中注解点(2)高于入参类型点(1),则该目标方法不可能匹配到切点@args(M) ,如下图所示

  • 如果在类继承树中注解点(2)低于入参类型点(1),则注解点所在类及其子孙类作为方法入参时,该方法匹配切点@args(M)

实例请参考下文。


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

args()

POJO

package com.xgj.aop.spring.advisor.aspectJ.function.args;import org.springframework.stereotype.Component;@Component
public class UserService {public void addUser(User user) {System.out.println("addUser " + user);}public void modifyUser(User user) {System.out.println("modifyUser " + user);}public void delUser(User user) {System.out.println("delUser " + user);}/*** * * @Title: addArtisanTT* * @Description: 入参为ArtisanTT* * @param artisan* * @return: void*/public void addArtisanTT(ArtisanTT artisan) {System.out.println("addArtisanTT " + artisan);}public void modifyArtisanTT(ArtisanTT artisan) {System.out.println("modifyArtisanTT " + artisan);}public void delArtisanTT(ArtisanTT artisan) {System.out.println("delArtisanTT " + artisan);}}

POJO

package com.xgj.aop.spring.advisor.aspectJ.function.args;import org.springframework.stereotype.Component;@Component
public class UserServiceExt {public void addUser(User user) {System.out.println("入参为user的类  addUser " + user);}public void modifyUser(User user) {System.out.println("入参为user的类   modifyUser " + user);}public void delUser(User user) {System.out.println("入参为user的类  delUser " + user);}/*** * * @Title: addArtisanTT* * @Description: 入参为ArtisanTT* * @param artisan* * @return: void*/public void addArtisanTT(ArtisanTT artisan) {System.out.println("addArtisanTT " + artisan);}public void modifyArtisanTT(ArtisanTT artisan) {System.out.println("modifyArtisanTT " + artisan);}public void delArtisanTT(ArtisanTT artisan) {System.out.println("delArtisanTT " + artisan);}
}

切面

package com.xgj.aop.spring.advisor.aspectJ.function.args;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;/*** * * @ClassName: ArgsAspectJ* * @Description: 该函数接收一个类名,表示目标类方法入参对象是指定类(包含子类)时,切点匹配* * @author: Mr.Yang* * @date: 2017年9月1日 上午11:36:23*/@Aspect
public class ArgsAspect {@Before("args(com.xgj.aop.spring.advisor.aspectJ.function.args.User)")public void crossCuttingCode() {System.out.println("some logic is here ");}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.args"/><!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/><!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.args.ArgsAspect"/></beans>

测试类:

package com.xgj.aop.spring.advisor.aspectJ.function.args;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ArgsAspectTest {private ApplicationContext ctx;@Testpublic void test() {ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/aop/spring/advisor/aspectJ/function/args/conf-args.xml");UserService userService = ctx.getBean("userService", UserService.class);UserServiceExt userServiceExt = ctx.getBean("userServiceExt", UserServiceExt.class);User user = new User();ArtisanTT artisan = new ArtisanTT();// 织入横切逻辑userService.addUser(user);// 织入横切逻辑userService.modifyUser(user);// 织入横切逻辑userService.delUser(user);System.out.println("================================");// 入参不是user,因此不会被织入横切逻辑userService.addArtisanTT(artisan);userService.modifyArtisanTT(artisan);userService.delArtisanTT(artisan);System.out.println("================================");// 入参为user,因此也会被织入横切逻辑userServiceExt.addUser(user);// 入参为user,因此也会被织入横切逻辑userServiceExt.modifyUser(user);// 入参为user,因此也会被织入横切逻辑userServiceExt.delUser(user);System.out.println("================================");// 入参不是user,因此不会被织入横切逻辑userServiceExt.addArtisanTT(artisan);userServiceExt.modifyArtisanTT(artisan);userServiceExt.delArtisanTT(artisan);}
}

运行结果:

2018-01-04 09:19:50,614  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4a05bc0c: startup date [Thu Jan 04 09:19:50 CST 2018]; root of context hierarchy
2018-01-04 09:19:50,795  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/args/conf-args.xml]
some logic is here
addUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
some logic is here
modifyUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
some logic is here
delUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
================================
addArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2
modifyArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2
delArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2
================================
some logic is here
入参为user的类  addUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
some logic is here
入参为user的类   modifyUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
some logic is here
入参为user的类  delUser com.xgj.aop.spring.advisor.aspectJ.function.args.User@657531ef
================================
addArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2
modifyArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2
delArtisanTT com.xgj.aop.spring.advisor.aspectJ.function.args.ArtisanTT@712175f2

@args()

首先我们先自定义一个注解,用于测试用

package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** * * @ClassName: Monitor* * @Description: 自定义注解 @Monitor*               更多信息请阅读http://blog.csdn.net/yangshangwei/article/*               details/77477840* * @author: Mr.Yang* * @date: 2017年9月1日 下午4:00:12*/@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
public @interface Monitor {public boolean value() default true;
}

使用注解扫描的4个POJO

package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.springframework.stereotype.Component;@Component
public class T0 {}
package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.springframework.stereotype.Component;@Component
public class T1 extends T0 {/*** * * @Title: fun* * @Description: 目标类方法,旨在这个方法中织入增强逻辑. 当注解标注在T2,方法的入参为T2或者T2的子孙类时,会织入增强* * @param t* * @return: void*/public void fun(T2 t) {System.out.println(t.getClass().getName() + " fun executed");}
}
package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.springframework.stereotype.Component;@Monitor
@Component
public class T2 extends T1 {}
package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.springframework.stereotype.Component;@Component
public class T3 extends T2 {}

切面

package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;/*** * * @ClassName: AtArgsAspect* * @Description: 标注了@Aspect的切面* * @author: Mr.Yang* * @date: 2017年9月1日 下午4:21:14*/@Aspect
public class AtArgsAspect {@Before("@args(com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.Monitor)")public void crossCuttingCode() {System.out.println("前置增强 横切逻辑织入 some logic is here ");}
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.args.atargs"/><!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/><!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.AtArgsAspect"/></beans>

测试类

package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AtArgsAspectTest {@Testpublic void test() {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/aop/spring/advisor/aspectJ/function/args/atargs/conf-atargs.xml");T0 t0 = ctx.getBean("t0", T0.class);T1 t1 = ctx.getBean("t1", T1.class);T2 t2 = ctx.getBean("t2", T2.class);T3 t3 = ctx.getBean("t3", T3.class);// 因t1中的fun入参为t2,且注解标注在了T2类上,t3又是t2的子类,所以 下面两个调用都会织入增强t1.fun(t2);t1.fun(t3);}
}

运行结果:

2017-09-04 17:43:44,302  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@f4efcb0: startup date [Mon Sep 04 17:43:44 BOT 2017]; root of context hierarchy
2017-09-04 17:43:44,390  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/args/atargs/conf-atargs.xml]
前置增强 横切逻辑织入 some logic is here
com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.T2$$EnhancerBySpringCGLIB$$fcff1873 fun executed
前置增强 横切逻辑织入 some logic is here
com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.T3$$EnhancerBySpringCGLIB$$109aa116 fun executed

从运行结果看,正确的织入了横切逻辑。

在类继承树中注解点低于入参类型点,则注解点所在类及其子孙类作为方法入参时,该方法匹配切点@args(M), 符合。


如果我们先取消掉T2上的@Monitor注解,然后把注解标注在T0上

如下:

package com.xgj.aop.spring.advisor.aspectJ.function.args.atargs;import org.springframework.stereotype.Component;@Monitor
@Component
public class T0 {}

运行结果:

2017-09-04 17:56:31,858  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1c057a1e: startup date [Mon Sep 04 17:56:31 BOT 2017]; root of context hierarchy
2017-09-04 17:56:31,970  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/args/atargs/conf-atargs.xml]
com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.T2$$EnhancerBySpringCGLIB$$42855f4c fun executed
com.xgj.aop.spring.advisor.aspectJ.function.args.atargs.T3$$EnhancerBySpringCGLIB$$5620e7ef fun executed

因在继承树中注解点高于入参类型点,因此该目标方法不可能匹配到切点@args(M)。

Spring-AOP @AspectJ切点函数之args()和@args()相关推荐

  1. 关于Spring AOP中切点修饰符@annotation、@args与args约束说明

    前言 于其说这是一篇文章,不如说这是一篇笔记,主要介绍了@annotation.@args和args的作用以及一些坑点.这里主要记录一些项目用到的,没有成一套体系,网上其他文章对Spring AOP的 ...

  2. 关于 Spring AOP (AspectJ) 你该知晓的一切

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/54629058 出自[zejian ...

  3. @AspectJ切点函数详解

    @AspectJ切点函数详解 1 方法切点函数 1.1 execution() 1.1.1 通过方法签名定义切点 1.1.2 通过类定义切点 1.1.3 通过类包定义切点 1.1.4 通过方法入参定义 ...

  4. @AspectJ切点函数之execution()

    @AspectJ切点函数之execution() execution()是最常用的切点函数,语法如下: execution(<修饰符模式>?<返回类型模式><方法名模式& ...

  5. Spring AOP + AspectJ Annotation Example---reference

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  6. Spring-AOP @AspectJ切点函数导读

    概述 annotation execution args和args within within和target target和this 概述 切点函数是AspectJ表达式语言的核心,也是使用@Aspe ...

  7. Spring AOP / AspectJ AOP 的区别?

    Spring AOP / AspectJ AOP 的区别? Spring AOP属于运行时增强,而AspectJ是编译时增强. Spring AOP基于代理(Proxying),而AspectJ基于字 ...

  8. 说说 Spring 支持的 AspectJ 切点函数

    1 @annotation() 它表示标注了某个注解的所有方法. 假设有一个接口 Cook,它有两个实现类 CookA.CookB: Cook: public interface Cook {/*** ...

  9. Spring-AOP @AspectJ切点函数之@within()和@target

    文章目录 概述 @target(M)的匹配规则 @within(M)的匹配规则 实例 @target @within 注意事项 概述 除了@annotation和@args外,还有另外两个用于注解的切 ...

最新文章

  1. 计算机网络谢希仁第七版课后答案第二章 物理层
  2. TCP/IP协议简介2
  3. (转)Arcgis for Js之鼠标经过显示对象名的实现
  4. javaScript调用函数失败
  5. mysql索引缓存的内容_mysql服务器变量、缓存及索引
  6. 你认识的有钱人,是怎么起家的?是做什么生意的?
  7. vue路由加载页面时,数据返回慢的问题
  8. PHP 安全检测代码片段
  9. 操作系统课程设计报告(文件系统)
  10. 查看计算机硬盘序列号的软件,硬盘序列号,手把手教你怎么查看硬盘序列号
  11. 一种基于A* 算法的动态多路径规划算法
  12. Flutter 弹出键盘报错解决
  13. mysql assoc什么意思_mysql_assoc
  14. Win10没有蓝牙功能怎么办 win10蓝牙图标不见了怎么办
  15. 关于iPhone改变的一切,这也许是史上最详细的盘点
  16. Python-文件夹的拷贝操作
  17. python加法例子_用python给小孩随机生成一组10以内加减法
  18. 计算机网络中英互译,计算机网络中英文互译.doc
  19. Docker搭建Maven私服和Gitlab
  20. android 平台 apk提取神器

热门文章

  1. C++基类和派生类的构造函数(二)
  2. python 操作 hbase
  3. 机器学习笔记:GRU
  4. R语言实战应用精讲50篇(十九)-R语言gganimate函数应用案例:静态图变成动态,让你的图表更酷炫
  5. 机器学习笔记——皮尔逊相关系数
  6. java状态模式例子答案_[转载]java设计模式_状态模式(带例子)
  7. 词云制作 Python
  8. Matplotlib-scatter-绘制散点图
  9. 唯品会订单分库分表的实践总结以及关键步骤--转
  10. mina应用程序架构(翻译)