AspectJ切入點(diǎn)語(yǔ)法詳解

Via http://jinnianshilongnian.iteye.com/blog/1415606


http://m.itdecent.cn/p/c4c86e75cf83

利用AspectJ實(shí)現(xiàn)Android端非侵入式埋點(diǎn)

https://eclipse.org/aspectj/doc/released/progguide/starting-aspectj.html

6.5? AspectJ切入點(diǎn)語(yǔ)法詳解

6.5.1? Spring AOP支持的AspectJ切入點(diǎn)指示符

切入點(diǎn)指示符用來(lái)指示切入點(diǎn)表達(dá)式目的,,在Spring AOP中目前只有執(zhí)行方法這一個(gè)連接點(diǎn),Spring AOP支持的AspectJ切入點(diǎn)指示符如下:

execution用于匹配方法執(zhí)行的連接點(diǎn);

within用于匹配指定類(lèi)型內(nèi)的方法執(zhí)行;

this用于匹配當(dāng)前AOP代理對(duì)象類(lèi)型的執(zhí)行方法;注意是AOP代理對(duì)象的類(lèi)型匹配,這樣就可能包括引入接口也類(lèi)型匹配;

target用于匹配當(dāng)前目標(biāo)對(duì)象類(lèi)型的執(zhí)行方法;注意是目標(biāo)對(duì)象的類(lèi)型匹配,這樣就不包括引入接口也類(lèi)型匹配;

args用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類(lèi)型的執(zhí)行方法;

@within用于匹配所以持有指定注解類(lèi)型內(nèi)的方法;

@target用于匹配當(dāng)前目標(biāo)對(duì)象類(lèi)型的執(zhí)行方法,其中目標(biāo)對(duì)象持有指定的注解;

@args用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行;

@annotation用于匹配當(dāng)前執(zhí)行方法持有指定注解的方法;

beanSpring AOP擴(kuò)展的,AspectJ沒(méi)有對(duì)于指示符,用于匹配特定名稱(chēng)的Bean對(duì)象的執(zhí)行方法;

reference pointcut表示引用其他命名切入點(diǎn),只有@ApectJ風(fēng)格支持,Schema風(fēng)格不支持。

AspectJ切入點(diǎn)支持的切入點(diǎn)指示符還有: call、get、set、preinitialization、staticinitialization、initialization、handler、adviceexecution、withincode、cflow、cflowbelow、if、@this、@withincode;但Spring AOP目前不支持這些指示符,使用這些指示符將拋出IllegalArgumentException異常。這些指示符Spring AOP可能會(huì)在以后進(jìn)行擴(kuò)展。

6.5.1? 命名及匿名切入點(diǎn)

命名切入點(diǎn)可以被其他切入點(diǎn)引用,而匿名切入點(diǎn)是不可以的。

只有@AspectJ支持命名切入點(diǎn),而Schema風(fēng)格不支持命名切入點(diǎn)。

如下所示,@AspectJ使用如下方式引用命名切入點(diǎn):

6.5.2??????? ;類(lèi)型匹配語(yǔ)法

首先讓我們來(lái)了解下AspectJ類(lèi)型匹配的通配符:

*:匹配任何數(shù)量字符;

..:匹配任何數(shù)量字符的重復(fù),如在類(lèi)型模式中匹配任何數(shù)量子包;而在方法參數(shù)模式中匹配任何數(shù)量參數(shù)。

+匹配指定類(lèi)型的子類(lèi)型;僅能作為后綴放在類(lèi)型模式后邊。

java代碼:

查看復(fù)制到剪貼板打印

java.lang.String????匹配String類(lèi)型;

java.*.String???????匹配java包下的任何“一級(jí)子包”下的String類(lèi)型;

如匹配java.lang.String,但不匹配java.lang.ss.String

java..*????????????匹配java包及任何子包下的任何類(lèi)型;

如匹配java.lang.String、java.lang.annotation.Annotation

java.lang.*ing??????匹配任何java.lang包下的以ing結(jié)尾的類(lèi)型;

java.lang.Number+??匹配java.lang包下的任何Number的自類(lèi)型;

如匹配java.lang.Integer,也匹配java.math.BigInteger

接下來(lái)再看一下具體的匹配表達(dá)式類(lèi)型吧:

匹配類(lèi)型:使用如下方式匹配

java代碼:

查看復(fù)制到剪貼板打印

注解??類(lèi)的全限定名字

注解:可選,類(lèi)型上持有的注解,如@Deprecated;

類(lèi)的全限定名:必填,可以是任何類(lèi)全限定名。

匹配方法執(zhí)行:使用如下方式匹配:

java代碼:

查看復(fù)制到剪貼板打印

注解??修飾符??返回值類(lèi)型?類(lèi)型聲明?方法名(參數(shù)列表)?異常列表?

注解:可選,方法上持有的注解,如@Deprecated;

修飾符:可選,如public、protected;

返回值類(lèi)型:必填,可以是任何類(lèi)型模式;“*”表示所有類(lèi)型;

類(lèi)型聲明:可選,可以是任何類(lèi)型模式;

方法名:必填,可以使用“*”進(jìn)行模式匹配;

參數(shù)列表:“()”表示方法沒(méi)有任何參數(shù);“(..)”表示匹配接受任意個(gè)參數(shù)的方法,“(..,java.lang.String)”表示匹配接受java.lang.String類(lèi)型的參數(shù)結(jié)束,且其前邊可以接受有任意個(gè)參數(shù)的方法;“(java.lang.String,..)” 表示匹配接受java.lang.String類(lèi)型的參數(shù)開(kāi)始,且其后邊可以接受任意個(gè)參數(shù)的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String類(lèi)型的參數(shù)結(jié)束,且其前邊接受有一個(gè)任意類(lèi)型參數(shù)的方法;

異常列表:可選,以“throws 異常全限定名列表”聲明,異常全限定名列表如有多個(gè)以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。

匹配Bean名稱(chēng):可以使用Bean的id或name進(jìn)行匹配,并且可使用通配符“*”;

6.5.3? 組合切入點(diǎn)表達(dá)式

AspectJ使用 且(&&)、或(||)、非(!)來(lái)組合切入點(diǎn)表達(dá)式。

在Schema風(fēng)格下,由于在XML中使用“&&”需要使用轉(zhuǎn)義字符“&&”來(lái)代替之,所以很不方便,因此Spring ASP 提供了and、or、not來(lái)代替&&、||、!。

6.5.3? 切入點(diǎn)使用示例

一、execution使用“execution(方法表達(dá)式)”匹配方法執(zhí)行;

模式

描述

public * *(..)

任何公共方法的執(zhí)行

* cn.javass..IPointcutService.*()

cn.javass包及所有子包下IPointcutService接口中的任何無(wú)參方法

* cn.javass..*.*(..)

cn.javass包及所有子包下任何類(lèi)的任何方法

* cn.javass..IPointcutService.*(*)

cn.javass包及所有子包下IPointcutService接口的任何只有一個(gè)參數(shù)方法

* (!cn.javass..IPointcutService+).*(..)

非“cn.javass包及所有子包下IPointcutService接口及子類(lèi)型”的任何方法

* cn.javass..IPointcutService+.*()

cn.javass包及所有子包下IPointcutService接口及子類(lèi)型的的任何無(wú)參方法

* cn.javass..IPointcut*.test*(java.util.Date)

cn.javass包及所有子包下IPointcut前綴類(lèi)型的的以test開(kāi)頭的只有一個(gè)參數(shù)類(lèi)型為java.util.Date的方法,注意該匹配是根據(jù)方法簽名的參數(shù)類(lèi)型進(jìn)行匹配的,而不是根據(jù)執(zhí)行時(shí)傳入的參數(shù)類(lèi)型決定的

如定義方法:public void test(Object obj);即使執(zhí)行時(shí)傳入java.util.Date,也不會(huì)匹配的;

* cn.javass..IPointcut*.test*(..)? throws

IllegalArgumentException, ArrayIndexOutOfBoundsExceptioncn.javass包及所有子包下IPointcut前綴類(lèi)型的的任何方法,且拋出IllegalArgumentException和ArrayIndexOutOfBoundsException異常

* (cn.javass..IPointcutService+

&& java.io.Serializable+).*(..)任何實(shí)現(xiàn)了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的類(lèi)型的任何方法

@java.lang.Deprecated * *(..)

任何持有@java.lang.Deprecated注解的方法

@java.lang.Deprecated @cn.javass..Secure ?* *(..)

任何持有@java.lang.Deprecated和@cn.javass..Secure注解的方法

@(java.lang.Deprecated || cn.javass..Secure) * *(..)

任何持有@java.lang.Deprecated或@ cn.javass..Secure注解的方法

(@cn.javass..Secure ?*)? *(..)

任何返回值類(lèi)型持有@cn.javass..Secure的方法

* ?(@cn.javass..Secure *).*(..)

任何定義方法的類(lèi)型持有@cn.javass..Secure的方法

* *(@cn.javass..Secure (*) , @cn.javass..Secure (*))

任何簽名帶有兩個(gè)參數(shù)的方法,且這個(gè)兩個(gè)參數(shù)都被@ Secure標(biāo)記了,

如public void test(@Secure String str1,

@Secure String str1);

* *((@ cn.javass..Secure *))或

* *(@ cn.javass..Secure *)任何帶有一個(gè)參數(shù)的方法,且該參數(shù)類(lèi)型持有@ cn.javass..Secure;

如public void test(Model model);且Model類(lèi)上持有@Secure注解

* *(

@cn.javass..Secure (@cn.javass..Secure *) ,

@ cn.javass..Secure (@cn.javass..Secure *))任何帶有兩個(gè)參數(shù)的方法,且這兩個(gè)參數(shù)都被@ cn.javass..Secure標(biāo)記了;且這兩個(gè)參數(shù)的類(lèi)型上都持有@ cn.javass..Secure;

* *(

java.util.Map

, ..)任何帶有一個(gè)java.util.Map參數(shù)的方法,且該參數(shù)類(lèi)型是以< cn.javass..Model, cn.javass..Model >為泛型參數(shù);注意只匹配第一個(gè)參數(shù)為java.util.Map,不包括子類(lèi)型;

如public void test(HashMap map, String str);將不匹配,必須使用“* *(

java.util.HashMap

, ..)”進(jìn)行匹配;

而public void test(Map map, int i);也將不匹配,因?yàn)榉盒蛥?shù)不匹配

* *(java.util.Collection<@cn.javass..Secure *>)

任何帶有一個(gè)參數(shù)(類(lèi)型為java.util.Collection)的方法,且該參數(shù)類(lèi)型是有一個(gè)泛型參數(shù),該泛型參數(shù)類(lèi)型上持有@cn.javass..Secure注解;

如public void test(Collection collection);Model類(lèi)型上持有@cn.javass..Secure

* *(java.util.Set)

任何帶有一個(gè)參數(shù)的方法,且傳入的參數(shù)類(lèi)型是有一個(gè)泛型參數(shù),該泛型參數(shù)類(lèi)型繼承與HashMap;

Spring AOP目前測(cè)試不能正常工作

* *(java.util.List)

任何帶有一個(gè)參數(shù)的方法,且傳入的參數(shù)類(lèi)型是有一個(gè)泛型參數(shù),該泛型參數(shù)類(lèi)型是HashMap的基類(lèi)型;如public voi test(Map map);

Spring AOP目前測(cè)試不能正常工作

* *(*<@cn.javass..Secure *>)

任何帶有一個(gè)參數(shù)的方法,且該參數(shù)類(lèi)型是有一個(gè)泛型參數(shù),該泛型參數(shù)類(lèi)型上持有@cn.javass..Secure注解;

Spring AOP目前測(cè)試不能正常工作

、within:使用“within(類(lèi)型表達(dá)式)匹配指定類(lèi)型內(nèi)的方法執(zhí)行;

模式

描述

within(cn.javass..*)

cn.javass包及子包下的任何方法執(zhí)行

within(cn.javass..IPointcutService+)

cn.javass包或所有子包下IPointcutService類(lèi)型及子類(lèi)型的任何方法

within(@cn.javass..Secure *)

持有cn.javass..Secure注解的任何類(lèi)型的任何方法

必須是在目標(biāo)對(duì)象上聲明這個(gè)注解,在接口上聲明的對(duì)它不起作用

、this使用“this(類(lèi)型全限定名)”匹配當(dāng)前AOP代理對(duì)象類(lèi)型的執(zhí)行方法;注意是AOP代理對(duì)象的類(lèi)型匹配,這樣就可能包括引入接口方法也可以匹配;注意this中使用的表達(dá)式必須是類(lèi)型全限定名,不支持通配符;

模式

描述

this(cn.javass.spring.chapter6.service.IPointcutService)

當(dāng)前AOP對(duì)象實(shí)現(xiàn)了 IPointcutService接口的任何方法

this(cn.javass.spring.chapter6.service.IIntroductionService)

當(dāng)前AOP對(duì)象實(shí)現(xiàn)了 IIntroductionService接口的任何方法

也可能是引入接口

四、target使用“target(類(lèi)型全限定名)”匹配當(dāng)前目標(biāo)對(duì)象類(lèi)型的執(zhí)行方法;注意是目標(biāo)對(duì)象的類(lèi)型匹配,這樣就不包括引入接口也類(lèi)型匹配;注意target中使用的表達(dá)式必須是類(lèi)型全限定名,不支持通配符;

模式

描述

target(cn.javass.spring.chapter6.service.IPointcutService)

當(dāng)前目標(biāo)對(duì)象(非AOP對(duì)象)實(shí)現(xiàn)了 IPointcutService接口的任何方法

target(cn.javass.spring.chapter6.service.IIntroductionService)

當(dāng)前目標(biāo)對(duì)象(非AOP對(duì)象) 實(shí)現(xiàn)了IIntroductionService 接口的任何方法

不可能是引入接口

五、args使用“args(參數(shù)類(lèi)型列表)”匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類(lèi)型的執(zhí)行方法;注意是匹配傳入的參數(shù)類(lèi)型,不是匹配方法簽名的參數(shù)類(lèi)型;參數(shù)類(lèi)型列表中的參數(shù)必須是類(lèi)型全限定名,通配符不支持;args屬于動(dòng)態(tài)切入點(diǎn),這種切入點(diǎn)開(kāi)銷(xiāo)非常大,非特殊情況最好不要使用;

模式

描述

args (java.io.Serializable,..)

任何一個(gè)以接受“傳入?yún)?shù)類(lèi)型為 java.io.Serializable” 開(kāi)頭,且其后可跟任意個(gè)任意類(lèi)型的參數(shù)的方法執(zhí)行,args指定的參數(shù)類(lèi)型是在運(yùn)行時(shí)動(dòng)態(tài)匹配的

六、@within使用“@within(注解類(lèi)型)”匹配所以持有指定注解類(lèi)型內(nèi)的方法;注解類(lèi)型也必須是全限定類(lèi)型名;

模式

描述

@within cn.javass.spring.chapter6.Secure)

任何目標(biāo)對(duì)象對(duì)應(yīng)的類(lèi)型持有Secure注解的類(lèi)方法;

必須是在目標(biāo)對(duì)象上聲明這個(gè)注解,在接口上聲明的對(duì)它不起作用

七、@target使用“@target(注解類(lèi)型)”匹配當(dāng)前目標(biāo)對(duì)象類(lèi)型的執(zhí)行方法,其中目標(biāo)對(duì)象持有指定的注解;注解類(lèi)型也必須是全限定類(lèi)型名;

模式

描述

@target (cn.javass.spring.chapter6.Secure)

任何目標(biāo)對(duì)象持有Secure注解的類(lèi)方法;

必須是在目標(biāo)對(duì)象上聲明這個(gè)注解,在接口上聲明的對(duì)它不起作用

八、@args使用“@args(注解列表)”匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行;注解類(lèi)型也必須是全限定類(lèi)型名;

模式

描述

@args (cn.javass.spring.chapter6.Secure)

任何一個(gè)只接受一個(gè)參數(shù)的方法,且方法運(yùn)行時(shí)傳入的參數(shù)持有注解 cn.javass.spring.chapter6.Secure;動(dòng)態(tài)切入點(diǎn),類(lèi)似于arg指示符;

九、@annotation使用“@annotation(注解類(lèi)型)”匹配當(dāng)前執(zhí)行方法持有指定注解的方法;注解類(lèi)型也必須是全限定類(lèi)型名;

模式

描述

@annotation(cn.javass.spring.chapter6.Secure )

當(dāng)前執(zhí)行方法上持有注解 cn.javass.spring.chapter6.Secure將被匹配

十、bean使用“bean(Bean id或名字通配符)匹配特定名稱(chēng)的Bean對(duì)象的執(zhí)行方法;Spring ASP擴(kuò)展的,在AspectJ中無(wú)相應(yīng)概念;

模式

描述

bean(*Service)

匹配所有以Service命名(id或name)結(jié)尾的Bean

十一、reference pointcut表示引用其他命名切入點(diǎn),只有@ApectJ風(fēng)格支持,Schema風(fēng)格不支持,如下所示:

比如我們定義如下切面:

java代碼:

查看復(fù)制到剪貼板打印

packagecn.javass.spring.chapter6.aop;

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Pointcut;

@Aspect

publicclassReferencePointcutAspect?{

@Pointcut(value="execution(*?*())")

publicvoidpointcut()?{}

}

可以通過(guò)如下方式引用:

java代碼:

查看復(fù)制到剪貼板打印

@Before(value?="cn.javass.spring.chapter6.aop.ReferencePointcutAspect.pointcut()")

publicvoidreferencePointcutTest2(JoinPoint?jp)?{}

除了可以在@AspectJ風(fēng)格的切面內(nèi)引用外,也可以在Schema風(fēng)格的切面定義內(nèi)引用,引用方式與@AspectJ完全一樣。

到此我們切入點(diǎn)表達(dá)式語(yǔ)法示例就介紹完了,我們這些示例幾乎包含了日常開(kāi)發(fā)中的所有情況,但當(dāng)然還有更復(fù)雜的語(yǔ)法等等,如果以上介紹的不能滿(mǎn)足您的需要,請(qǐng)參考AspectJ文檔。

由于測(cè)試代碼相當(dāng)長(zhǎng),所以為了節(jié)約篇幅本示例代碼在cn.javass.spring.chapter6. PointcutTest文件中,需要時(shí)請(qǐng)參考該文件。

6.6? 通知參數(shù)

前邊章節(jié)已經(jīng)介紹了聲明通知,但如果想獲取被被通知方法參數(shù)并傳遞給通知方法,該如何實(shí)現(xiàn)呢?接下來(lái)我們將介紹兩種獲取通知參數(shù)的方式。

使用JoinPoint獲取:Spring AOP提供使用org.aspectj.lang.JoinPoint類(lèi)型獲取連接點(diǎn)數(shù)據(jù),任何通知方法的第一個(gè)參數(shù)都可以是JoinPoint(環(huán)繞通知是ProceedingJoinPoint,JoinPoint子類(lèi)),當(dāng)然第一個(gè)參數(shù)位置也可以是JoinPoint.StaticPart類(lèi)型,這個(gè)只返回連接點(diǎn)的靜態(tài)部分。

1) JoinPoint提供訪(fǎng)問(wèn)當(dāng)前被通知方法的目標(biāo)對(duì)象、代理對(duì)象、方法參數(shù)等數(shù)據(jù):

java代碼:

查看復(fù)制到剪貼板打印

packageorg.aspectj.lang;

importorg.aspectj.lang.reflect.SourceLocation;

publicinterfaceJoinPoint?{

String?toString();//連接點(diǎn)所在位置的相關(guān)信息

String?toShortString();//連接點(diǎn)所在位置的簡(jiǎn)短相關(guān)信息

String?toLongString();//連接點(diǎn)所在位置的全部相關(guān)信息

Object?getThis();//返回AOP代理對(duì)象

Object?getTarget();//返回目標(biāo)對(duì)象

Object[]?getArgs();//返回被通知方法參數(shù)列表

Signature?getSignature();//返回當(dāng)前連接點(diǎn)簽名

SourceLocation?getSourceLocation();//返回連接點(diǎn)方法所在類(lèi)文件中的位置

String?getKind();//連接點(diǎn)類(lèi)型

StaticPart?getStaticPart();//返回連接點(diǎn)靜態(tài)部分

}

2ProceedingJoinPoint:用于環(huán)繞通知,使用proceed()方法來(lái)執(zhí)行目標(biāo)方法:

java代碼:

查看復(fù)制到剪貼板打印

publicinterfaceProceedingJoinPointextendsJoinPoint?{

publicObject?proceed()throwsThrowable;

publicObject?proceed(Object[]?args)throwsThrowable;

}

3) JoinPoint.StaticPart提供訪(fǎng)問(wèn)連接點(diǎn)的靜態(tài)部分,如被通知方法簽名、連接點(diǎn)類(lèi)型等:

java代碼:

查看復(fù)制到剪貼板打印

publicinterfaceStaticPart?{

Signature?getSignature();//返回當(dāng)前連接點(diǎn)簽名

String?getKind();//連接點(diǎn)類(lèi)型

intgetId();//唯一標(biāo)識(shí)

String?toString();//連接點(diǎn)所在位置的相關(guān)信息

String?toShortString();//連接點(diǎn)所在位置的簡(jiǎn)短相關(guān)信息

String?toLongString();//連接點(diǎn)所在位置的全部相關(guān)信息

}

使用如下方式在通知方法上聲明,必須是在第一個(gè)參數(shù),然后使用jp.getArgs()就能獲取到被通知方法參數(shù):

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="execution(*?sayBefore(*))")

publicvoidbefore(JoinPoint?jp)?{}

@Before(value="execution(*?sayBefore(*))")

publicvoidbefore(JoinPoint.StaticPart?jp)?{}

自動(dòng)獲?。?/b>通過(guò)切入點(diǎn)表達(dá)式可以將相應(yīng)的參數(shù)自動(dòng)傳遞給通知方法,例如前邊章節(jié)講過(guò)的返回值和異常是如何傳遞給通知方法的。

在Spring AOP中,除了execution和bean指示符不能傳遞參數(shù)給通知方法,其他指示符都可以將匹配的相應(yīng)參數(shù)或?qū)ο笞詣?dòng)傳遞給通知方法。

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="execution(*?test(*))?&&?args(param)",?argNames="param")

publicvoidbefore1(String?param)?{

System.out.println("===param:"+?param);

}

切入點(diǎn)表達(dá)式execution(* test(*)) && args(param) :

1)首先execution(* test(*))匹配任何方法名為test,且有一個(gè)任何類(lèi)型的參數(shù);

2)args(param)將首先查找通知方法上同名的參數(shù),并在方法執(zhí)行時(shí)(運(yùn)行時(shí))匹配傳入的參數(shù)是使用該同名參數(shù)類(lèi)型,即java.lang.String;如果匹配將把該被通知參數(shù)傳遞給通知方法上同名參數(shù)。

其他指示符(除了execution和bean指示符)都可以使用這種方式進(jìn)行參數(shù)綁定。

在此有一個(gè)問(wèn)題,即前邊提到的類(lèi)似于【3.1.2構(gòu)造器注入】中的參數(shù)名注入限制:class文件中沒(méi)生成變量調(diào)試信息是獲取不到方法參數(shù)名字的。

所以我們可以使用策略來(lái)確定參數(shù)名:

如果我們通過(guò)“argNames”屬性指定了參數(shù)名,那么就是要我們指定的;

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="?args(param)",?argNames="param")//明確指定了

publicvoidbefore1(String?param)?{

System.out.println("===param:"+?param);

}

如果第一個(gè)參數(shù)類(lèi)型是JoinPoint、ProceedingJoinPoint或JoinPoint.StaticPart類(lèi)型,應(yīng)該從“argNames”屬性省略掉該參數(shù)名(可選,寫(xiě)上也對(duì)),這些類(lèi)型對(duì)象會(huì)自動(dòng)傳入的,但必須作為第一個(gè)參數(shù);

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="?args(param)",?argNames="param")//明確指定了

publicvoidbefore1(JoinPoint?jp,?String?param)?{

System.out.println("===param:"+?param);

}

如果“class文件中含有變量調(diào)試信息”將使用這些方法簽名中的參數(shù)名來(lái)確定參數(shù)名;

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="?args(param)")//不需要argNames了

publicvoidbefore1(JoinPoint?jp,?String?param)?{

System.out.println("===param:"+?param);

}

如果沒(méi)有“class文件中含有變量調(diào)試信息”,將嘗試自己的參數(shù)匹配算法,如果發(fā)現(xiàn)參數(shù)綁定有二義性將拋出AmbiguousBindingException異常;對(duì)于只有一個(gè)綁定變量的切入點(diǎn)表達(dá)式,而通知方法只接受一個(gè)參數(shù),說(shuō)明綁定參數(shù)是明確的,從而能配對(duì)成功。

java代碼:

查看復(fù)制到剪貼板打印

@Before(value="?args(param)")

publicvoidbefore1(JoinPoint?jp,?String?param)?{

System.out.println("===param:"+?param);

}

以上策略失敗將拋出IllegalArgumentException。

接下來(lái)讓我們示例一下組合情況吧:

java代碼:

查看復(fù)制到剪貼板打印

@Before(args(param)?&&?target(bean)?&&@annotation(secure)",

argNames="jp,param,bean,secure")

publicvoidbefore5(JoinPoint?jp,?String?param,

IPointcutService?pointcutService,?Secure?secure)?{

……

}

該示例的執(zhí)行步驟如圖6-5所示。

圖6-5 參數(shù)自動(dòng)獲取流程

除了上邊介紹的普通方式,也可以對(duì)使用命名切入點(diǎn)自動(dòng)獲取參數(shù):

java代碼:

查看復(fù)制到剪貼板打印

@Pointcut(value="args(param)",?argNames="param")

privatevoidpointcut1(String?param){}

@Pointcut(value="@annotation(secure)",?argNames="secure")

privatevoidpointcut2(Secure?secure){}

@Before(value?="pointcut1(param)?&&?pointcut2(secure)",

argNames="param,?secure")

publicvoidbefore6(JoinPoint?jp,?String?param,?Secure?secure)?{

……

}

自此給通知傳遞參數(shù)已經(jīng)介紹完了,示例代碼在cn.javass.spring.chapter6.ParameterTest文件中。

在Spring配置文件中,所以AOP相關(guān)定義必須放在標(biāo)簽下,該標(biāo)簽下可以有、、標(biāo)簽,配置順序不可變。

:用來(lái)定義切入點(diǎn),該切入點(diǎn)可以重用;

:用來(lái)定義只有一個(gè)通知和一個(gè)切入點(diǎn)的切面;

:用來(lái)定義切面,該切面可以包含多個(gè)切入點(diǎn)和通知,而且標(biāo)簽內(nèi)部的通知和切入點(diǎn)定義是無(wú)序的;和advisor的區(qū)別就在此,advisor只包含一個(gè)通知和一個(gè)切入點(diǎn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容