您的位置:首页技术文章
文章详情页

通过实例解析Spring argNames属性

浏览:69日期:2023-07-31 17:25:01

最近学习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@Aspectpublic 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/beanshttp://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 class='bean.HelloApi'></bean> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

输出:

2 a:b b:a1 a:a b:bin 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:a1 a:a b:b

PS:

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

通过实例解析Spring argNames属性

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持好吧啦网。

标签: Spring
相关文章: