通過(guò)實(shí)例解析Spring argNames屬性
最近學(xué)習(xí)Spring,一直不太明白Srping的切面編程中的的argNames的含義,經(jīng)過(guò)學(xué)習(xí)研究后,終于明白,分享一下
需要監(jiān)控的類:
package bean; public class HelloApi { public void aspectTest(String a,String b){ System.out.println("in aspectTest:" + "a:" + a + ",b:" + b); } }
類HelloApi的aspectTest方法是需監(jiān)控的方法,目標(biāo)是調(diào)用前獲取獲得入?yún)和b的值,并打印出來(lái)。
切面類:
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的區(qū)別是argNames的順序交換了 @Before(value="pointcut1(a,b)",argNames="b,a") public void beforecase2(String a,String b){ System.out.println("2 a:" + a +" b:" + b); } }
測(cè)試類:
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
說(shuō)明:
HelloApiAspect2定義了一個(gè)切面pointcut,切面表達(dá)式是execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2),表示配對(duì)bean.HelloApi.aspectTest()方法,并且傳入?yún)?shù)是2個(gè)。
args(a1,b2)另外一個(gè)作用,就是定義了aspectTest(String a,String b)方法對(duì)應(yīng)表達(dá)式args(a1,b2)。定義了args(a1,b2),才能把目標(biāo)方法aspectTest的參數(shù)傳入到切面方法beforecase1的參數(shù)中,a參數(shù)對(duì)應(yīng)a1,b參數(shù)對(duì)應(yīng)b2。使用的方法是按順序一一對(duì)應(yīng),aspectTest第一個(gè)參數(shù)對(duì)args第一個(gè)參數(shù),aspectTest第2個(gè)參數(shù)對(duì)args第2個(gè)參數(shù).
argNames是可選的,如果沒(méi)有argNames這個(gè)參數(shù),而編譯器設(shè)置了【在class文件生成變量調(diào)試信息】,則spring可以通過(guò)反射知道方法參數(shù)的名字,通過(guò)名字配對(duì),Spring知道args(a1,b2)表達(dá)式里面的a1和b2,對(duì)應(yīng)了pointcut1(String a1,String b2)方法里面的a1和b2。
目標(biāo)方法和切入方法的參數(shù)的關(guān)系是這樣確立的:aspectTest(String a,String b) 與 args(a1,b2)關(guān)系是a對(duì)a1,b對(duì)b2(),args(a1,b2)與pointcut1(String a1,String b2)關(guān)系是args的a1對(duì)pointcut1的a1,args的a2對(duì)pointcut1的a2。解決了目標(biāo)方法參數(shù)傳入到切入方法參數(shù)的問(wèn)題。
但是,如果設(shè)置了argNames,Spring不再使用方法參數(shù)的名字來(lái)配對(duì),使用argNames定義的順序來(lái)定義pointcut1(String a1,String b2)的順序,例如:argNames="a1,b2",a1在b2前面,表示pointcut1方法第一個(gè)參數(shù)是a1,第二個(gè)參數(shù)是b2。
既然不設(shè)置argNames,Spring可以根據(jù)參數(shù)名字進(jìn)行配對(duì),為什么還需要配置argNames?因?yàn)镾pring要知道方法的參數(shù)名,編譯器必須設(shè)置了【在class文件生成變量調(diào)試信息】,如果沒(méi)有設(shè)置,Spring就不知道pointcut1方法的參數(shù)名了,這個(gè)時(shí)候,Spring只知道參數(shù)的類型,Spring會(huì)使用參數(shù)的類型進(jìn)行配對(duì),如果出現(xiàn)2個(gè)參數(shù)都是同一個(gè)類型的情況,就會(huì)報(bào)AmbiguousBindingException異常。
beforecase1和beforecase2的argNames設(shè)置的順序交換了,調(diào)用beforecase1的順序是beforecase1("a","b"),調(diào)用beforecase2的順序是beforecase2("b","a"),所以最后的輸出是
2 a:b b:a
1 a:a b:b
PS:
【class文件中生成變量調(diào)試信息】在myeclipse中打開(kāi)windows-》preferences,設(shè)置如下:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)簡(jiǎn)單碰撞檢測(cè)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單碰撞檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java使用Poi導(dǎo)出Excel表格方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Java使用Poi導(dǎo)出Excel表格的相關(guān)資料,Java POI是一個(gè)用于操作Microsoft Office格式的Java API庫(kù),可以使用它來(lái)導(dǎo)出Excel文件,需要的朋友可以參考下2023-10-10基于NIO的Netty網(wǎng)絡(luò)框架(詳解)
下面小編就為大家?guī)?lái)一篇基于NIO的Netty網(wǎng)絡(luò)框架(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06如何在攔截器中獲取url路徑里面@PathVariable的參數(shù)值
這篇文章主要介紹了如何在攔截器中獲取url路徑里面@PathVariable的參數(shù)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08java基于dom4j包實(shí)現(xiàn)對(duì)XML解析的方法
這篇文章主要介紹了java基于dom4j包實(shí)現(xiàn)對(duì)XML解析的方法,結(jié)合實(shí)例形式分析了java針對(duì)xml格式數(shù)據(jù)的相關(guān)解析操作實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-05-05教你如何監(jiān)控 Java 線程池運(yùn)行狀態(tài)的操作(必看)
這篇文章主要介紹了教你如何監(jiān)控 Java 線程池運(yùn)行狀態(tài)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02JAVA 格式化JSON數(shù)據(jù)并保存到j(luò)son文件中的實(shí)例
這篇文章主要介紹了JAVA 格式化JSON數(shù)據(jù)并保存到j(luò)son文件中的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10