02 AOP切入點詳解

Spring AOP支持的AspectJ切入點指示符

Spring AOP支持的AspectJ切入點指示符如下:

指示符 含義
execution 用于匹配方法執(zhí)行的連接點啸驯;
within 用于匹配指定類型內(nèi)的方法執(zhí)行;
this 用于匹配當(dāng)前AOP代理對象類型的執(zhí)行方法;注意是AOP代理對象的類型匹配碘饼,這樣就可能包括引入接口也類型匹配厚柳;
target 用于匹配當(dāng)前目標(biāo)對象類型的執(zhí)行方法涡尘;注意是 目標(biāo)對象的類型匹配悔捶,這樣就不包括引入接口也類型匹配;
args 用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類型的執(zhí)行方法炎功;
@within 用于匹配所以持有指定注解類型內(nèi)的方法枚冗;
@target 用于匹配當(dāng)前目標(biāo)對象類型的執(zhí)行方法蛇损,其中目標(biāo)對象持有指定的注解;
@args 用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行淤齐;
@annotation 用于匹配當(dāng)前執(zhí)行方法持有指定注解的方法股囊;
bean Spring AOP擴展的,AspectJ沒有對于指示符更啄,用于匹配特定名稱的Bean對象的執(zhí)行方法;
reference pointcut 表示引用其他命名切入點内狗,只有@ApectJ風(fēng)格支持义锥,Schema風(fēng)格不支持。

類型匹配語法

首先讓我們來了解下AspectJ類型匹配的通配符:

*:匹配任何數(shù)量字符赂鲤;
..:匹配任何數(shù)量字符的重復(fù),如在類型模式中匹配任何數(shù)量子包数初;而在方法參數(shù)模式中匹配任何數(shù)量參數(shù)泡孩。
+:匹配指定類型的子類型;僅能作為后綴放在類型模式后邊珍德。

例如:

樣例 說明
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結(jié)尾的類型
java.lang.Number+ 匹配java.lang包下的任何Number的自類型获列;如匹配java.lang.Integer,也匹配java.math.BigInteger

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

  1. 匹配類:使用如下方式匹配

    注解? 類的全限定名字
    - 注解:可選迫悠,類型上持有的注解巩梢,如@Deprecated;
    - 類的全限定名:必填鞠抑,可以是任何類全限定名忌警。

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

    注解? 修飾符? 返回值類型 類型聲明?方法名(參數(shù)列表) 異常列表?
    - 注解:可選,方法上持有的注解箕速,如@Deprecated礼烈;
    - 修飾符:可選此熬,如public、protected犀忱;
    - 返回值類型:必填阴汇,可以是任何類型模式;“”表示所有類型拐纱;
    - 類型聲明:可選哥倔,可以是任何類型模式;
    - 方法名:必填东抹,可以使用“
    ”進行模式匹配沃测;
    - 參數(shù)列表:“()”表示方法沒有任何參數(shù);“(..)”表示匹配接受任意個參數(shù)的方法馏谨,“(..,java.lang.String)”表示匹配接受java.lang.String類型的參數(shù)結(jié)束附迷,且其前邊可以接受有任意個參數(shù)的方法挟秤;“(java.lang.String,..)” 表示匹配接受java.lang.String類型的參數(shù)開始,且其后邊可以接受任意個參數(shù)的方法艘刚;“(*,java.lang.String)” 表示匹配接受java.lang.String類型的參數(shù)結(jié)束攀甚,且其前邊接受有一個任意類型參數(shù)的方法;
    - 異常列表:可選炸庞,以“throws 異常全限定名列表”聲明荚斯,異常全限定名列表如有多個以“查牌,”分割纸颜,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException绎橘。

  3. 匹配Bean名稱:可以使用Bean的id或name進行匹配,并且可使用通配符“*”

組合切入點表達(dá)式

AspectJ使用 且(&&)涮较、或(||)冈止、非(!)來組合切入點表達(dá)式苫亦。

切入點使用示例

  1. execution:使用“execution(方法表達(dá)式)”匹配方法執(zhí)行

    模式 描述
    public * *(..) 任何公共方法的執(zhí)行
    * com.learn..IHelloService.*() com.learn包及所有子包下IHelloService接口中的任何無參方法
    * com.learn..*.*(..) com.learn包及所有子包下任何類的任何方法
    * com.learn..IHelloService.*(*) com.learn包及所有子包下IHelloService接口的任何只有一個參數(shù)方法
    * (!com.learn..IHelloService+).*(..) 非“com.learn包及所有子包下IHelloService接口及子類型”的任何方法
    * com.learn..IHelloService+.*() com.learn包及所有子包下IHelloService接口及子類型的的任何無參方法
    * com.learn..IHelloService*.test*(java.util.Date) com.learn包及所有子包下IHelloService前綴類型的的以test開頭的只有一個參數(shù)類型為java.util.Date的方法屋剑,注意該匹配是根據(jù)方法簽名的參數(shù)類型進行匹配的诗眨,而不是根據(jù)執(zhí)行時傳入的參數(shù)類型決定的,如定義方法:public void test(Object obj);即使執(zhí)行時傳入java.util.Date巍膘,也不會匹配的芋簿;
    * com.learn..IHelloService.test(..) throws IllegalArgumentException, ArrayIndexOutOfBoundsException com.learn包及所有子包下IHelloService前綴類型的的任何方法与斤,且拋出IllegalArgumentException和ArrayIndexOutOfBoundsException異常
    * (com.learn..IHelloService+ && java.io.Serializable+).*(..) 任何實現(xiàn)了com.learn包及所有子包下 IHelloService接口和java.io.Serializable接口的類型的任何方法
    @java.lang.Deprecated * *(..) 任何持有@java.lang.Deprecated注解的方法
    @(java.lang.Deprecated || com.learn..Secure) * *(..) 任何持有@java.lang.Deprecated或@com.learn..Secure注解的方法
    (@com.learn..Secure *) *(..) 任何返回值類型持有@com.learn..Secure的方法
    * (@com.learn..Secure *).*(..) 任何定義方法的類型持有@com.learn..Secure的方法
    * *(@com.learn..Secure (*) , @com.learn..Secure (*)) 任何簽名帶有兩個參數(shù)的方法,且這個兩個參數(shù)都被@Secure標(biāo)記了磷支,如public void test(@Secure String str1, @Secure String str1)
    * *((@ com.learn..Secure *))或 * *(@ com.learn..Secure *) 任何帶有一個參數(shù)的方法雾狈,且該參數(shù)類型持有@com.learn..Secure抵皱;如public void test(Model model);且Model類上持有@Secure注解
    * *( @com.learn..Secure (@com.learn..Secure *) , @ com.learn..Secure (@com.learn..Secure *)) 任何帶有兩個參數(shù)的方法辩蛋,且這兩個參數(shù)都被@com.learn..Secure標(biāo)記了锭弊;且這兩個參數(shù)的類型上都持有@ com.learn..Secure味滞;
    * *( java.util.Map<com.learn..Model, com.learn..Model> , ..) 任何帶有一個java.util.Map參數(shù)的方法钮呀,且該參數(shù)類型是以< com.learn..Model, com.learn..Model >為泛型參數(shù);注意只匹配第一個參數(shù)為java.util.Map,不包括子類型蚁署;如public void test(HashMap<Model, Model> map, String str);將不匹配蚂四,必須使用“* *( java.util.HashMap<com.learn..Model,com.learn..Model> , ..)”進行匹配; 而public void test(Map map, int i);也將不匹配久妆,因為泛型參數(shù)不匹配 * *(java.util.Collection<@com.learn..Secure *>) 任何帶有一個參數(shù)(類型為java.util.Collection)的方法全度,且該參數(shù)類型是有一個泛型參數(shù),該泛型參數(shù)類型上持有@com.learn..Secure注解; 如public void test(Collection<Model> collection);Model類型上持有@com.learn..Secure * *(java.util.Set<? extends HashMap>) 任何帶有一個參數(shù)的方法蜕乡,且傳入的參數(shù)類型是有一個泛型參數(shù)层玲,該泛型參數(shù)類型繼承與HashMap; Spring AOP目前測試不能正常工作
    * *(java.util.List<? super HashMap>) 任何帶有一個參數(shù)的方法扣癣,且傳入的參數(shù)類型是有一個泛型參數(shù)憨降,該泛型參數(shù)類型是HashMap的基類型;如public voi test(Map map)士嚎;Spring AOP目前測試不能正常工作
    * *(*<@com.learn..Secure *>) 任何帶有一個參數(shù)的方法,且該參數(shù)類型是有一個泛型參數(shù)爵嗅,該泛型參數(shù)類型上持有@com.learn..Secure注解笨蚁;Spring AOP目前測試不能正常工作
  1. within:使用“within(類型表達(dá)式)”匹配指定類型內(nèi)的方法執(zhí)行括细;

    模式 描述
    within(com.learn..*) com.learn包及子包下的任何方法執(zhí)行
    within(com.learn..IHelloService+) com.learn包或所有子包下IHelloService類型及子類型的任何方法
    within(@com.learn..Secure *) 持有com.learn..Secure注解的任何類型的任何方法,必須是在目標(biāo)對象上聲明這個注解锉试,在接口上聲明的對它不起作用
  1. 模式 描述
    this(com.learn.model.Member) 當(dāng)前AOP對象實現(xiàn)了Member接口/抽象類的某些方法览濒,Member的父類未重載的方法不會被處理

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

    模式 描述
    this(com.learn.model.Member) 當(dāng)前AOP對象實現(xiàn)了Member接口/抽象類的某些方法奖磁,Member的父類未重載的方法不會被處理
  2. target:使用“target(類型全限定名)”匹配當(dāng)前目標(biāo)對象類型的執(zhí)行方法繁疤;注意 是目標(biāo)對象的類型匹配稠腊,這樣就不包括引入接口也類型匹配;注意target中使用的表達(dá)式必須是類型全限定名架忌,不支持通配符

    模式 描述
    target(com.learn.model.Member) 當(dāng)前目標(biāo)對象(非AOP對象)實現(xiàn)了Member接口/抽象類的某些方法,Member的父類未重載的方法也會被處理
  3. args:使用“args(參數(shù)類型列表)”匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類型的執(zhí)行方法挠羔;注意是匹配傳入的參數(shù)類型埋嵌,不是匹配方法簽名的參數(shù)類型;參數(shù)類型列表中的參數(shù)必須是類型全限定名范舀,通配符不支持俐银;args屬于動態(tài)切入點端仰,這種切入點開銷非常大荔烧,非特殊情況最好不要使用

    模式 描述
    args (com.learn.model.Member,..) 任何一個以接受“傳入?yún)?shù)類型為com.learn.model.Member” 開頭,且其后可跟任意個任意類型的參數(shù)的方法執(zhí)行踊餐,args指定的參數(shù)類型是在運行時動態(tài)匹配的
  4. @within:使用“@within(注解類型)”匹配所有持有指定注解類型內(nèi)的方法臀稚;注解類型也必須是全限定類型名

    模式 描述
    @within(com.learn.annotation.Secure) 任何目標(biāo)對象對應(yīng)的類型持有Secure注解的類方法吧寺; 必須是在目標(biāo)對象上聲明這個注解, 在接口上聲明的對它不起作用
  5. @target:使用“@target(注解類型)”匹配當(dāng)前目標(biāo)對象類型的執(zhí)行方法幕帆,其中目標(biāo)對象持有指定的注解赖条;注解類型也必須是全限定類型名

    模式 描述
    @target(com.learn.annotation.Secure) 任何目標(biāo)對象持有Secure注解的類方法; 必須是在目標(biāo)對象上聲明這個注解碱茁,在接口上聲明的對它不起作用
  6. @args:使用“@args(注解列表)”匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行仿贬;注解類型也必須是全限定類型名

    模式 描述
    @args(com.learn.annotation.Secure) 任何一個只接受一個參數(shù)的方法诅蝶,且方法運行時傳入的參數(shù)持有注解com.learn.annotation.Secure募壕;動態(tài)切入點语盈,類似于arg指示符
  7. @annotation:使用“@annotation(注解類型)”匹配當(dāng)前執(zhí)行方法持有指定注解的方法刀荒;注解類型也必須是全限定類型名;

    模式 描述
    @annotation(com.learn.annotation.Secure) 當(dāng)前執(zhí)行方法上持有注解com.learn.annotation.Secure將被匹配
  8. bean:使用“bean(Bean id或名字通配符)”匹配特定名稱的Bean對象的執(zhí)行方法干毅;Spring ASP擴展的泼返,在AspectJ中無相應(yīng)概念;

    模式 描述
    bean(*Service) 匹配所有以Service命名(id或name)結(jié)尾的Bean
  9. reference pointcut: 表示引用其他命名切入點渠鸽, 只有@ApectJ風(fēng)格支持徽缚,Schema風(fēng)格不支持革屠,如下所示:
    比如我們定義如下切面:

@Aspect
public class HelloServiceAspect {
    //匹配com.learn.service.impl包及其子包下的所有類的所有方法
    @Pointcut("execution(* com.learn.service.impl..*.*(..))")
    public void executeService(){ }
}

可以通過如下方式引用:

@Aspect
@Component
public class HelloServiceExecutor {
    @Before("com.learn.aop.HelloServiceAspect.executeService()")
    public void doBeforeAdvice(){
        System.out.println("我是前置通知!!!");
    }
}

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

目錄
源碼鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呻率,一起剝皮案震驚了整個濱河市礼仗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌韭脊,老刑警劉巖单旁,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件象浑,死亡現(xiàn)場離奇詭異,居然都是意外死亡篓吁,警方通過查閱死者的電腦和手機蚪拦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門外盯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事狼渊”芬兀” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵糕伐,是天一觀的道長蘸嘶。 經(jīng)常有香客問我训唱,道長,這世上最難降的妖魔是什么赞庶? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮澜薄,結(jié)果婚禮上摊册,老公的妹妹穿的比我還像新娘。我一直安慰自己蟆沫,他們只是感情好温治,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布熬荆。 她就那樣靜靜地躺著,像睡著了一般累盗。 火紅的嫁衣襯著肌膚如雪突琳。 梳的紋絲不亂的頭發(fā)上拆融,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機與錄音傲须,去河邊找鬼趟脂。 笑死昔期,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咬最。 我是一名探鬼主播欠动,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼翅雏!你這毒婦竟也來了望几?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤靴迫,失蹤者是張志新(化名)和其女友劉穎楼誓,沒想到半個月后疟羹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡参淫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年涎才,在試婚紗的時候發(fā)現(xiàn)自己被綠了民效。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畏邢。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡检吆,死狀恐怖蹭沛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摊灭,我是刑警寧澤帚呼,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站眷蜈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辜妓。R本人自食惡果不足惜忌怎,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一榴啸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灰瞻,春花似錦辅甥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脐供。三九已至,卻和暖如春酌壕,著一層夾襖步出監(jiān)牢的瞬間歇由,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谢谦,地道東北人萝衩。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓船侧,卻偏偏與公主長得像欠气,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子镜撩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359