1. 程式人生 > 程式設計 >通過例項解析Spring argNames屬性

通過例項解析Spring argNames屬性

最近學習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,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屬性

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。