@Pointcut語法詳解

https://www.mekau.com/4880.html
https://blog.csdn.net/xiaoyiaoyou/article/details/45972363

定義

格式:@ 註解(value=“表達標籤 ( 表達式格式)”)
如:@Pointcut (value=“execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(…))”)

表達式標籤

  • execution():用於匹配方法執行的連接點
  • args(): 用於匹配當前執行的方法傳入的參數爲指定類型的執行方法
  • this(): 用於匹配當前AOP代理對象類型的執行方法;注意是AOP代理對象的類型匹配,這樣就可能包括引入接口也類型匹配;
  • target(): 用於匹配當前目標對象類型的執行方法;注意是目標對象的類型匹配,這樣就不包括引入接口也類型匹配;
  • within(): 用於匹配指定類型內的方法執行;
  • @args():於匹配當前執行的方法傳入的參數持有指定註解的執行;
  • @target():用於匹配當前目標對象類型的執行方法,其中目標對象持有指定的註解;
  • @within():用於匹配所以持有指定註解類型內的方法;
  • @annotation:用於匹配當前執行方法持有指定註解的方法;

其中execution 是用的最多的,

execution

execution格式:

execution(modifier-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
其中帶 ?號的 modifiers-pattern?,declaring-type-pattern?,hrows-pattern?是可選項
ret-type-pattern,name-pattern, parameters-pattern是必選項;

  • modifier-pattern? 修飾符匹配,如public 表示匹配公有方法
  • ret-type-pattern 返回值匹配,* 表示任何返回值,全路徑的類名等
  • declaring-type-pattern? 類路徑匹配
  • name-pattern 方法名匹配,* 代表所有,set*,代表以set開頭的所有方法
  • (param-pattern) 參數匹配,指定方法參數(聲明的類型),
    (…)代表所有參數,
    ()代表一個參數,
    (
    ,String)代表第一個參數爲任何值,第二個爲String類型.
  • throws-pattern? 異常類型匹配

例子:

  • execution(public * *(..)) 定義任意公共方法的執行
  • execution(* set*(..)) 定義任何一個以"set"開始的方法的執行
  • execution(* com.xyz.service.AccountService.*(..)) 定義AccountService 接口的任意方法的執行
  • execution(* com.xyz.service.*.*(..)) 定義在service包裏的任意方法的執行
  • execution(* com.xyz.service ..*.*(..)) 定義在service包和所有子包裏的任意類的任意方法的執行
  • execution(* com.test.spring.aop.pointcutexp…JoinPointObjP2.*(…)) 定義在pointcutexp包和所有子包裏的JoinPointObjP2類的任意方法的執行:
    (..),.(..)),JoinPointObjP2.(..))\color{red}{說明:最靠近(..)的爲方法名,靠近.*(..))的爲類名或者接口名,如上例的JoinPointObjP2.*(..))}

AspectJ類型匹配的通配符:

  • * \color{blue}{匹配任何數量字符;}
  • . . \color{blue}{匹配任何數量字符的重複,如在類型模式中匹配任何數量子包;而在方法參數模式中匹配任何數量參數。}
  • +:\color{blue}{匹配指定類型的子類型;僅能作爲後綴放在類型模式後邊。}

如:

  • java.lang.String 匹配String類型;
  • java.*.String 匹配java包下的任何“一級子包”下的String類型;如匹配java.lang.String,但不匹配java.lang.ss.String
  • java..* 匹配java包及任何子包下的任何類型; 如匹配java.lang.String、java.lang.annotation.Annotation
  • java.lang.*ing 匹配任何java.lang包下的以ing結尾的類型;
  • java.lang.Number+ 匹配java.lang包下的任何Number的自類型;如匹配java.lang.Integer,也匹配java.math.BigInteger

within和@within

  • within(com.test.spring.aop.pointcutexp.*) pointcutexp包裏的任意類.
  • within(com.test.spring.aop.pointcutexp…*) pointcutexp包和所有子包裏的任意類.
  • @within(org.springframework.transaction.annotation.Transactional) 帶有@Transactional標註的所有類的任意方法.

this

  • this(com.test.spring.aop.pointcutexp.Intf) 實現了Intf接口的所有類,如果Intf不是接口,限定Intf單個類.

AOP,getBeancast,.\color{red}{當一個實現了接口的類被AOP的時候,用getBean方法必須cast爲接口類型,不能爲該類的類型.}

@target

  • @target(org.springframework.transaction.annotation.Transactional) 帶有@Transactional標註的所有類的任意方法.

@annotation

  • @annotation(org.springframework.transaction.annotation.Transactional) 帶有@Transactional標註的任意方法.
    @within@target,@annotation\color{red}{@within和@target針對類的註解,@annotation是針對方法的註解}

args 和 @args

  • @args(org.springframework.transaction.annotation.Transactional) 參數帶有@Transactional標註的方法.
  • args(String) 參數爲String類型(運行是決定)的方法.

命名及匿名切入點

Pointcut,使&&!\color{red}{Pointcut定義時,還可以使用\&\&、 || 、! 運算符}

@Pointcut("execution(* com.savage.aop.MessageSender.*(..)) && args(param)")
public void log(){
}
@Before("log(String param)") 
 public void beforeLog(){
     //todo something....
 }
 //等同於
@Before("execution(* com.savage.aop.MessageSender.*(..)) && args(param)") 
 public void beforeLog(){
     //todo something....
 }

又如:

@Pointcut("execution(* com.savage.aop.MessageSender.*(..))")
    private void logSender(){}

    @Pointcut("execution(* com.savage.aop.MessageReceiver.*(..))")
    private void logReceiver(){}

    @Pointcut("logSender() || logReceiver()")
    private void logMessage(){} 

這個例子中,logMessage()將匹配任何MessageSender和MessageReceiver中的任何方法

切入點使用示例:

  • 一、execution:使用“execution(方法表達式)”匹配方法執行;
示例 描述
public * *(…) 任何公共方法的執行
* cn.javass…IPointcutService.*() cn.javass包及所有子包下IPointcutService接口中的任何無參方法
* cn.javass….(…) cn.javass包及所有子包下任何類的任何方法
* cn.javass…IPointcutService.() cn.javass包及所有子包下IPointcutService接口的任何只有一個參數方法
* (!cn.javass…IPointcutService+).*(…) 非“cn.javass包及所有子包下IPointcutService接口及子類型”的任何方法
* cn.javass…IPointcutService+.*() cn.javass包及所有子包下IPointcutService接口及子類型的的任何無參方法
* cn.javass…IPointcut*.test*(java.util.Date) cn.javass包及所有子包下IPointcut前綴類型的的以test開頭的只有一個參數類型爲java.util.Date的方法,注意該匹配是根據方法簽名的參數類型進行匹配的,而不是根據執行時傳入的參數類型決定的,如定義方法:public void test(Object obj);即使執行時傳入java.util.Date,也不會匹配的;
* cn.javass…IPointcut*.test*(…) throws IllegalArgumentException,ArrayIndexOutOfBoundsException,cn.javass 包及所有子包下IPointcut前綴類型的的任何方法,且拋出IllegalArgumentException和ArrayIndexOutOfBoundsException異常
* (cn.javass…IPointcutService+&& java.io.Serializable+).*(…) 任何實現了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的類型的任何方法
@java.lang.Deprecated * *(…) 任何持有@java.lang.Deprecated註解的方法
@java.lang.Deprecated @cn.javass…Secure * *(…) 任何持有@java.lang.Deprecated和@cn.javass…Secure註解的方法
@(java.lang.Deprecated
(@cn.javass…Secure *) *(…) 任何返回值類型持有@cn.javass…Secure的方法
* (@cn.javass…Secure ).(…) 任何定義方法的類型持有@cn.javass…Secure的方法
* (@cn.javass…Secure () , @cn.javass…Secure (*)) 任何簽名帶有兩個參數的方法,且這個兩個參數都被@ Secure標記了,如public void test(@Secure String str1, @Secure String str1);
* *((@ cn.javass…Secure ))或 *(@ cn.javass…Secure *) 任何帶有一個參數的方法,且該參數類型持有@ cn.javass…Secure;
如public void test(Model model);且Model類上持有@Secure註解
* *(@cn.javass…Secure (@cn.javass…Secure *) ,@ cn.javass…Secure (@cn.javass…Secure *)) 任何帶有兩個參數的方法,且這兩個參數都被@ cn.javass…Secure標記了;且這兩個參數的類型上都持有@ cn.javass…Secure;
* *(java.util.Map<cn.javass…Model, cn.javass…Model>, …) 任何帶有一個java.util.Map參數的方法,且該參數類型是以< cn.javass…Model, cn.javass…Model >爲泛型參數;注意只匹配第一個參數爲java.util.Map,不包括子類型;如public void test(HashMap<Model, Model> map, String str);將不匹配,必須使用“* *(java.util.HashMap<cn.javass…Model,cn.javass…Model>, …)”進行匹配;而public void test(Map map, int i);也將不匹配,因爲泛型參數不匹配
* *(java.util.Collection<@cn.javass…Secure *>) 任何帶有一個參數(類型爲java.util.Collection)的方法,且該參數類型是有一個泛型參數,該泛型參數類型上持有@cn.javass…Secure註解;如public void test(Collection collection);Model類型上持有@cn.javass…Secure
* *(java.util.Set<? extends HashMap>) 任何帶有一個參數的方法,且傳入的參數類型是有一個泛型參數,該泛型參數類型繼承與HashMap;Spring AOP目前測試不能正常工作
* *(java.util.List<? super HashMap>) 任何帶有一個參數的方法,且傳入的參數類型是有一個泛型參數,該泛型參數類型是HashMap的基類型;如public voi test(Map map);Spring AOP目前測試不能正常工作
* (<@cn.javass…Secure *>) 任何帶有一個參數的方法,且該參數類型是有一個泛型參數,該泛型參數類型上持有@cn.javass…Secure註解;Spring AOP目前測試不能正常工作
  • 二、within:使用“within(類型表達式)”匹配指定類型內的方法執行;
示例 描述
within(cn.javass…*) cn.javass包及子包下的任何方法執行
within(cn.javass…IPointcutService+) cn.javass包或所有子包下IPointcutService類型及子類型的任何方法
within(@cn.javass…Secure *) 持有cn.javass…Secure註解的任何類型的任何方法必須是在目標對象上聲明這個註解,在接口上聲明的對它不起作用
  • 三、this:使用“this(類型全限定名)”匹配當前AOP代理對象類型的執行方法;注意是AOP代理對象的類型匹配,這樣就可能包括引入接口方法也可以匹配;注意this中使用的表達式必須是類型全限定名,不支持通配符;
示例 描述
this(cn.javass.spring.chapter6.service.IPointcutService) 當前AOP對象實現了 IPointcutService接口的任何方法
this(cn.javass.spring.chapter6.service.IIntroductionService) 當前AOP對象實現了 IIntroductionService接口的任何方法
  • 四、target:使用“target(類型全限定名)”匹配當前目標對象類型的執行方法;注意是目標對象的類型匹配,這樣就不包括引入接口也類型匹配;注意target中使用的表達式必須是類型全限定名,不支持通配符;
示例 描述
target(cn.javass.spring.chapter6.service.IPointcutService) 當前目標對象(非AOP對象)實現了 IPointcutService接口的任何方法
target(cn.javass.spring.chapter6.service.IIntroductionService) 當前目標對象(非AOP對象) 實現了IIntroductionService 接口的任何方法, 不可能是引入接口
  • 五、args:使用“args(參數類型列表)”匹配當前執行的方法傳入的參數爲指定類型的執行方法;注意是匹配傳入的參數類型,不是匹配方法簽名的參數類型;參數類型列表中的參數必須是類型全限定名,通配符不支持;args屬於動態切入點,這種切入點開銷非常大,非特殊情況最好不要使用;
示例 描述
args (java.io.Serializable,…) 任何一個以接受“傳入參數類型爲 java.io.Serializable” 開頭,且其後可跟任意個任意類型的參數的方法執行,args指定的參數類型是在運行時動態匹配的
  • 六、@within:使用“@within(註解類型)”匹配所以持有指定註解類型內的方法;註解類型也必須是全限定類型名;
示例 描述
@within(cn.javass.spring.chapter6.Secure) 任何目標對象對應的類型持有Secure註解的類方法;
  • 七、@target:使用“@target(註解類型)”匹配當前目標對象類型的執行方法,其中目標對象持有指定的註解;註解類型也必須是全限定類型名;
示例 描述
@target (cn.javass.spring.chapter6.Secure) 任何目標對象持有Secure註解的類方法;必須是在目標對象上聲明這個註解,在接口上聲明的對它不起作用
  • 八、@args:使用“@args(註解列表)”匹配當前執行的方法傳入的參數持有指定註解的執行;註解類型也必須是全限定類型名;
示例 描述
@args (cn.javass.spring.chapter6.Secure) 任何一個只接受一個參數的方法,且方法運行時傳入的參數持有註解 cn.javass.spring.chapter6.Secure;動態切入點,類似於arg指示符;
  • 九、@annotation:使用“@annotation(註解類型)”匹配當前執行方法持有指定註解的方法;註解類型也必須是全限定類型名;
示例 描述
@annotation(cn.javass.spring.chapter6.Secure ) 當前執行方法上持有註解 cn.javass.spring.chapter6.Secure將被匹配
  • 十、bean:使用“bean(Bean id或名字通配符)”匹配特定名稱的Bean對象的執行方法;Spring ASP擴展的,在AspectJ中無相應概念;
示例 描述
bean(*Service) 匹配所有以Service命名(id或name)結尾的Bean
  • 十一、reference pointcut:表示引用其他命名切入點;
@Pointcut(value="bean(*Service)")
private void pointcut1(){
}
@Pointcut(value="@args()cn.javass.spring.chaper6.Source")
public referencePointcutTest(JoinPoint jp){
     ...
}

AOP例子

@Aspect
@Component
public class NotVeryUsefulAspect {
	@AfterReturning(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..))")
	private void logReceiver(){
		System.out.println("切入點logReceiver...");
	}

	@Pointcut(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..)) && args(param)")
	private void pointcut(String param){ 
		System.out.println("切入點pointcut()"+param);
	}

	//方法體將不執行
	@Pointcut("within(com.cn.spring.aspectj.*)")
	public String inWebLayer() {
		System.out.println("切入點inWebLayer()");
		return "返回值加載";
	}

	@Before(value="inWebLayer()")
		private void beforeinWebLayer(){ 
		System.out.println("beforeinWebLayer~~");
	}

	@Before(value="pointcut(param)")
		private void beforePointcut(String param){ 
		System.out.println("beforePointcut:"+param);
	}


	@AfterReturning(pointcut="inWebLayer()",returning="retVal")
		public void doAccessCheck(Object retVal) {
		System.out.println("doAccessCheck:"+retVal);
	}

	@Around(value="execution(* com.cn.spring.aspectj.NotVeryUsefulAspectService.*(..))")
	private Object aroundLayer(ProceedingJoinPoint pjp) throws Throwable{ 
		// start stopwatch
		Object retVal = pjp.proceed();
		// stop stopwatch
		System.out.println("aroundLayer~~");
		return retVal;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章