Spring中argNames的含義

最近學習Spring,一直不太明白Srping的切面編程中的的argNames的含義,通過學習研究後,終於明白,分享一下java

先看一個例子:spring

 

須要監控的類:編程

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的值,並打印出來。windows

 

切面類:api

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); } }
 

測試類:eclipse

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

說明:spa

  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異常。

  beforecase1beforecase2的argNames設置的順序交換了,調用beforecase1的順序是beforecase1("a","b"),調用beforecase2的順序是beforecase2("b","a"),因此最後的輸出是

 

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

 

 

PS:

【class文件中生成變量調試信息】在myeclipse中打開windows-》preferences,設置以下:

相關文章
相關標籤/搜索