最近学习Spring,一直不太明白Srping的切面编程中的的argNames的含义,经过学习研究后,终于明白,分享一下

先看一个例子:

需要监控的类:

package bean;

public class HelloApi {

    public void aspectTest(String a,String b){
System.out.println("in aspectTest:" + "a:" + a + ",b:" + b);
}
}

类HelloApi的aspectTest方法是需监控的方法,目标是调用前获取获得入参a和b的值,并打印出来。

切面类:

package aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; import java.lang.String; @Component
@Aspect
public class HelloApiAspect2 { @Pointcut(value="execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2)",argNames="a1,b2")
public void pointcut1(String a1,String b2){} @Before(value="pointcut1(a,b)",argNames="a,b")
public void beforecase1(String a,String b){
System.out.println("1 a:" + a +" b:" + b);
}
//注意和beforecase1的区别是argNames的顺序交换了
@Before(value="pointcut1(a,b)",argNames="b,a")
public void beforecase2(String a,String b){
System.out.println("2 a:" + a +" b:" + b);
} }
 

测试类:

package UnitTest;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext; import bean.HelloApi; public class Test1 { @Test
public void aspectjTest1(){
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/aspectTest1.xml");
HelloApi helloapi1 = beanFactory.getBean("helloapi1",HelloApi.class);
helloapi1.aspectTest("a", "b");
}
}

Spring的配置文件aspectTest.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="aspect"></context:component-scan> <bean id="helloapi1" class="bean.HelloApi"></bean>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

输出:

2 a:b b:a
1 a:a b:b
in aspectTest:a:a,b:b

说明:

  HelloApiAspect2定义了一个切面pointcut,切面表达式是execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2),表示配对bean.HelloApi.aspectTest()方法,并且传入参数是2个。
args(a1,b2)另外一个作用,就是定义了aspectTest(String a,String b)方法对应表达式args(a1,b2)。定义了args(a1,b2),才能把目标方法aspectTest的参数传入到切面方法beforecase1的参数中,a参数对应a1,b参数对应b2。使用的方法是按顺序一一对应,aspectTest第一个参数对args第一个参数,aspectTest第2个参数对args第2个参数.
  argNames是可选的,如果没有argNames这个参数,而编译器设置了【在class文件生成变量调试信息】,则spring可以通过反射知道方法参数的名字,通过名字配对,Spring知道args(a1,b2)表达式里面的a1和b2,对应了pointcut1(String a1,String b2)方法里面的a1和b2。

  目标方法和切入方法的参数的关系是这样确立的:aspectTest(String a,String b) 与 args(a1,b2)关系是a对a1,b对b2(),args(a1,b2)与pointcut1(String a1,String b2)关系是args的a1对pointcut1的a1,args的a2对pointcut1的a2。解决了目标方法参数传入到切入方法参数的问题。

  但是,如果设置了argNames,Spring不再使用方法参数的名字来配对,使用argNames定义的顺序来定义pointcut1(String a1,String b2)的顺序,例如:argNames="a1,b2",a1在b2前面,表示pointcut1方法第一个参数是a1,第二个参数是b2。

  既然不设置argNames,Spring可以根据参数名字进行配对,为什么还需要配置argNames?因为Spring要知道方法的参数名,编译器必须设置了【在class文件生成变量调试信息】,如果没有设置,Spring就不知道pointcut1方法的参数名了,这个时候,Spring只知道参数的类型,Spring会使用参数的类型进行配对,如果出现2个参数都是同一个类型的情况,就会报AmbiguousBindingException异常。

  beforecase1和beforecase2的argNames设置的顺序交换了,调用beforecase1的顺序是beforecase1("a","b"),调用beforecase2的顺序是beforecase2("b","a"),所以最后的输出是

2 a:b b:a
1 a:a b:b

PS:

【class文件中生成变量调试信息】在myeclipse中打开windows-》preferences,设置如下:

Spring中argNames的含义的更多相关文章

  1. 深入理解spring中的各种注解

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

  2. 简单解析依赖注入(控制反转)在Spring中的应用

    IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者 ...

  3. Spring中的事务管理

    事务简介: 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性 事务就是一系列的动作,它们被当作一个单独的工作单元.这些动作要么全部完成,要么全部不起作用 事务的四个关键属性( ...

  4. Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

  5. 深入理解spring中的各种注解(转)

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

  6. Spring 中使用Quartz实现任务调度

    前言:Spring中使用Quartz 有两种方式,一种是继承特定的基类:org.springframework.scheduling.quartz.QuartzJobBean,另一种则不需要,(推荐使 ...

  7. 剑指Offer——企业级项目中分层的含义与依据及多态的优势

    剑指Offer--企业级项目中分层的含义与依据及多态的优势   关于以上两点,由于项目经验较少,自己不是很明白,特整理如下. 常见分层架构模式 三层架构 3-tier architecture   微 ...

  8. Spring中的AOP 专题

    Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...

  9. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

随机推荐

  1. 最小生成树------Prim算法

    定义:设G=(V,E)是一个无向连通图.如果G的生成子图T=(V,E’)是一棵树,则称T是G的一棵生成树(Spanning Tree). 应用生成树可以得到关于一个电网的一组独立的回路方程.第一步是要 ...

  2. RGBa颜色 css3的Alpha通道支持

    CSS3中,RGBa 为颜色声明添加Alpha通道. RGB值被指定使用3个8位无符号整数(0 – 255)并分别代表红色.蓝色.和绿色.增加的一个alpha通道并不是一个颜色通道——它只是用来指定除 ...

  3. JavaScript 零散知识点1 (正则表达式+定时器+hover)

    1.clear:both清楚浮动影响//css中 2.正则表达式 search方法 :指明是否存在相应的匹配,如找到一个返回一个整数值,表明这个匹配距离字符串开始的偏移位置,如果没有找到匹配返回-1f ...

  4. 聊聊css盒子模型

    css盒子模型原理: 在网页设计中常听的属性名:内容(content).填充/内边距(padding).边框(border).外边距(margin), CSS盒子模式都具备这些属性. 这些属性我们可以 ...

  5. php图片等比例缩放

    新建文件index.php,需要在统计目录下有个图片为q.jpg(可根据源码进行更改图片的名称) 源代码如下: <?php$filename="q.jpg"; $per=0. ...

  6. Android IntentService使用

    因为多数启动服务不必同时处理多个请求(在多线程情景下会很危险),所以使用IntentService类实现服务是很好的选择.本经验将通过继承IntentService输出当前时间教大家如何使用Inten ...

  7. iOS崩溃日志分析

    Incident Identifier: 55864905-937C-4172-B435-2ACA13D3070ECrashReporter Key: b85cab13431711060a5fab55 ...

  8. Array.splice返回值是数组

    import flash.display.MovieClip; import flash.display.DisplayObject; var m:MovieClip = new MovieClip( ...

  9. CodeForces 538B

    Description A number is called quasibinary if its decimal representation contains only digits 0 or 1 ...

  10. 【转】c#文件操作大全(一)

    1.创建文件夹//using System.IO;Directory.CreateDirectory(%%1); 2.创建文件//using System.IO;File.Create(%%1); 3 ...