通過實(shí)例解析Spring argNames屬性
最近學(xué)習(xí)Spring,一直不太明白Srping的切面編程中的的argNames的含義,經(jīng)過學(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的值,并打印出來。
切面類:
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);
}
}
測試類:
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定義了一個(gè)切面pointcut,切面表達(dá)式是execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2),表示配對bean.HelloApi.aspectTest()方法,并且傳入?yún)?shù)是2個(gè)。
args(a1,b2)另外一個(gè)作用,就是定義了aspectTest(String a,String b)方法對應(yīng)表達(dá)式args(a1,b2)。定義了args(a1,b2),才能把目標(biāo)方法aspectTest的參數(shù)傳入到切面方法beforecase1的參數(shù)中,a參數(shù)對應(yīng)a1,b參數(shù)對應(yīng)b2。使用的方法是按順序一一對應(yīng),aspectTest第一個(gè)參數(shù)對args第一個(gè)參數(shù),aspectTest第2個(gè)參數(shù)對args第2個(gè)參數(shù).
argNames是可選的,如果沒有argNames這個(gè)參數(shù),而編譯器設(shè)置了【在class文件生成變量調(diào)試信息】,則spring可以通過反射知道方法參數(shù)的名字,通過名字配對,Spring知道args(a1,b2)表達(dá)式里面的a1和b2,對應(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對a1,b對b2(),args(a1,b2)與pointcut1(String a1,String b2)關(guān)系是args的a1對pointcut1的a1,args的a2對pointcut1的a2。解決了目標(biāo)方法參數(shù)傳入到切入方法參數(shù)的問題。
但是,如果設(shè)置了argNames,Spring不再使用方法參數(shù)的名字來配對,使用argNames定義的順序來定義pointcut1(String a1,String b2)的順序,例如:argNames="a1,b2",a1在b2前面,表示pointcut1方法第一個(gè)參數(shù)是a1,第二個(gè)參數(shù)是b2。
既然不設(shè)置argNames,Spring可以根據(jù)參數(shù)名字進(jìn)行配對,為什么還需要配置argNames?因?yàn)镾pring要知道方法的參數(shù)名,編譯器必須設(shè)置了【在class文件生成變量調(diào)試信息】,如果沒有設(shè)置,Spring就不知道pointcut1方法的參數(shù)名了,這個(gè)時(shí)候,Spring只知道參數(shù)的類型,Spring會(huì)使用參數(shù)的類型進(jìn)行配對,如果出現(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中打開windows-》preferences,設(shè)置如下:

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java?POI導(dǎo)出Excel時(shí)合并單元格沒有邊框的問題解決
這篇文章主要給大家介紹了關(guān)于Java?POI導(dǎo)出Excel時(shí)合并單元格沒有邊框的問題解決辦法,文中通過代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-07-07
Spring Boot實(shí)現(xiàn)對文件進(jìn)行壓縮下載功能
在Web應(yīng)用中,文件下載功能是一個(gè)常見的需求,特別是當(dāng)你需要提供用戶下載各種類型的文件時(shí),本文將演示如何使用Spring Boot框架來實(shí)現(xiàn)一個(gè)簡單而強(qiáng)大的文件下載功能,需要的朋友跟隨小編一起學(xué)習(xí)吧2023-09-09
Spring?Boot用戶注冊驗(yàn)證的實(shí)現(xiàn)全過程記錄
最近在設(shè)計(jì)自己的博客系統(tǒng),涉及到用戶注冊與登錄驗(yàn)證,所以下面這篇文章主要給大家介紹了關(guān)于Spring?Boot用戶注冊驗(yàn)證的實(shí)現(xiàn)全過程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-01-01
Spring Security+Spring Data Jpa如何進(jìn)行安全管理
這篇文章主要介紹了Spring Security+Spring Data Jpa如何進(jìn)行安全管理,幫助大家更好的理解和學(xué)習(xí)Spring Security框架,感興趣的朋友可以了解下2020-09-09
解析java稀疏數(shù)組如何幫助我們節(jié)省內(nèi)存提升性能
這篇文章主要為大家介紹了java稀疏數(shù)組如何幫助我們節(jié)省內(nèi)存提升性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11

