日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring AOP中定义切点(PointCut)和通知(Advice)

發(fā)布時間:2025/3/21 javascript 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring AOP中定义切点(PointCut)和通知(Advice) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文討論一下Spring AOP編程中的兩個關(guān)鍵問題,定義切點和定義通知,理解這兩個問題能應(yīng)付大部分AOP場景。

如果你還不熟悉AOP,請先看AOP基本原理,本文的例子也沿用了AOP基本原理中的例子。

切點表達式

切點的功能是指出切面的通知應(yīng)該從哪里織入應(yīng)用的執(zhí)行流。切面只能織入公共方法。

在Spring AOP中,使用AspectJ的切點表達式語言定義切點其中excecution()是最重要的描述符,其它描述符用于輔助excecution()。

excecution()的語法如下

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

這個語法看似復(fù)雜,但是我們逐個分解一下,其實就是描述了一個方法的特征:

問號表示可選項,即可以不指定。

excecution(* com.tianmaying.service.BlogService.updateBlog(..))

  • modifier-pattern:表示方法的修飾符
  • ret-type-pattern:表示方法的返回值
  • declaring-type-pattern?:表示方法所在的類的路徑
  • name-pattern:表示方法名
  • param-pattern:表示方法的參數(shù)
  • throws-pattern:表示方法拋出的異常

注意事項

  • 其中后面跟著“?”的是可選項。
  • 在各個pattern中,可以使用"*"來表示匹配所有。
  • param-pattern中,可以指定具體的參數(shù)類型,多個參數(shù)間用“,”隔開,各個也可以用“*”來表示匹配任意類型的參數(shù),如(String)表示匹配一個String參數(shù)的方法;(*,String)表示匹配有兩個參數(shù)的方法,第一個參數(shù)可以是任意類型,而第二個參數(shù)是String類型。
  • 可以用(..)表示零個或多個任意的方法參數(shù)。

使用&&符號表示與關(guān)系,使用||表示或關(guān)系、使用!表示非關(guān)系。在XML文件中使用and、or和not這三個符號。

在切點中引用Bean

Spring還提供了一個bean()描述符,用于在切點表達式中引用Spring Beans。例如:

excecution(* com.tianmaying.service.BlogService.updateBlog(..)) and bean('tianmayingBlog')

這表示將切面應(yīng)用于BlogService的updateBlog方法上,但是僅限于ID為tianmayingBlog的Bean。

也可以排除特定的Bean:

excecution(* com.tianmaying.service.BlogService.updateBlog(..)) and !bean('tianmayingBlog')

其它切點描述符

其它可用的描述符包括:

  • args()

  • @args()

  • execution()

  • this()

  • target()

  • @target()

  • within()

  • @within()

  • @annotation

當(dāng)你有更加復(fù)雜的切點需要描述時,你可能可以用上這些描述符,通過這些你可以設(shè)置目標(biāo)類實現(xiàn)的接口、方法和類擁有的標(biāo)注等信息。具體可以參考Spring的官方文檔。

這里一共有9個描述符,execution()前面已經(jīng)詳細討論過,其它幾個可以做一個簡單的分類:

  • this()是用來限定方法所屬的類,比如this(com.tianmaying.service.BlogServiceInterface)表示實現(xiàn)了com.tianmaying.service.BlogServiceInterface的所有類。如果this括號內(nèi)是具體類而不是接口的話,則表示單個類。

  • @annotation表示具有某個標(biāo)注的方法,比如@annotation(org.springframework.transaction.annotation.Transactional)表示被Transactional標(biāo)注的方法

  • args?表示方法的參數(shù)屬于一個特定的類

  • within?表示方法屬于一個特定的類

  • target?表示方法所屬的類

  • 它們對應(yīng)的加了@的版本則表示對應(yīng)的類具有某個標(biāo)注。

單獨定義切點

詳細了解了定義切點之后,在回顧上一節(jié)中的代碼:

package com.tianmaying.aopdemo.aspect;import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;@Aspect //1 @Component public class LogAspect {@Pointcut("execution(* com.tianmaying.aopdemo..*.bookFlight(..))") //2private void logPointCut() {}@AfterReturning(pointcut = "logPointCut()", returning = "retVal") //3public void logBookingStatus(boolean retVal) { //4if (retVal) {System.out.println("booking flight succeeded!");} else {System.out.println("booking flight failed!");}} }

可以看到通過標(biāo)注方式定義切點只需要兩個步驟:

  • 定義一個空方法
  • 使用@Piontcut標(biāo)注,填入切點表達式
  • @AfterReturning(pointcut = "execution(* com.tianmaying.aopdemo..*.bookFlight(..))", returning = "retVal")中通過pointcout = "logPointCut"引用了這個切點。當(dāng)然也可以在@AfterReturning()直接定義切點表達式,如:

    @AfterReturning(pointcut = "logPointCut()", returning = "retVal") //3

    推薦使用前一種方法,因為這樣可以在多個通知中復(fù)用切點的定義。

    切點定義實例

    這里我們給出一些切點的定義實例。

    @Pointcut("execution(public * *(..))") // 1 private void anyPublicOperation() {}@Pointcut("within(com.xyz.someapp.web..*))") // 2 private void inTrading() {}@Pointcut("anyPublicOperation() && inTrading()") // 3 private void tradingOperation() {}@within(org.springframework.transaction.annotation.Transactional) // 4 private void transactionalClass() {}@annotation(org.springframework.transaction.annotation.Transactional) //5 private void transactionalMethod() {}

    上面的代碼定義了三個切點:

  • 任意公共方法(實際應(yīng)用中一般不會定義這樣的切點)
  • 在within(com.xyz.someapp.web包或者其子包下任意類的方法
  • 同時滿足切點1和切點2條件的切點,這里使用了&&符號
  • 標(biāo)注了Transactional的類的方法
  • 標(biāo)注了Transactional的方法
  • 定義通知

    依然回到TimeRecordingAspect的代碼:

    @Aspect @Component public class TimeRecordingAspect {@Pointcut("execution(* com.tianmaying.aopdemo..*.bookFlight(..))")private void timeRecordingPointCut() {}@Around("timeRecordingPointCut()") //1public Object recordTime(ProceedingJoinPoint pjp) throws Throwable { //2long start = System.currentTimeMillis();Object retVal = pjp.proceed(); // 3long duration = System.currentTimeMillis() - start;System.out.println(String.format("time for booking flight is %d seconds", duration));return retVal;} }

    定義了切點之后,我們需要定義何時調(diào)用recordTime方法記錄時間,即需要定義通知。

    AspectJ提供了五種定義通知的標(biāo)注:

    • @Before:前置通知,在調(diào)用目標(biāo)方法之前執(zhí)行通知定義的任務(wù)
    • @After:后置通知,在目標(biāo)方法執(zhí)行結(jié)束后,無論執(zhí)行結(jié)果如何都執(zhí)行通知定義的任務(wù)
    • @After-returning:后置通知,在目標(biāo)方法執(zhí)行結(jié)束后,如果執(zhí)行成功,則執(zhí)行通知定義的任務(wù)
    • @After-throwing:異常通知,如果目標(biāo)方法執(zhí)行過程中拋出異常,則執(zhí)行通知定義的任務(wù)
    • @Around:環(huán)繞通知,在目標(biāo)方法執(zhí)行前和執(zhí)行后,都需要執(zhí)行通知定義的任務(wù)

    通過標(biāo)注定義通知只需要兩個步驟:

  • 將以上五種標(biāo)注之一添加到切面的方法中
  • 在標(biāo)注中設(shè)置切點的定義
  • 創(chuàng)建環(huán)繞通知

    環(huán)繞通知相比其它四種通知有其特殊之處。環(huán)繞通知本質(zhì)上是將前置通知、后置通知和異常通知整合成一個單獨的通知。

    用@Around標(biāo)注的方法,該方法必須有一個ProceedingJoinPoint類型的參數(shù),比如上面代碼中的recordTime的簽名:

    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable

    在方法體中,需要通過這個參數(shù),以joinPoint.proceed();的形式調(diào)用目標(biāo)方法。注意在環(huán)繞通知中必須進行該調(diào)用,否則目標(biāo)方法本身的執(zhí)行就會被跳過。

    比如在recoredTime的實現(xiàn)中:

    long start = System.currentTimeMillis(); Object retVal = pjp.proceed(); long duration = System.currentTimeMillis() - start; System.out.println(String.format("time for booking flight is %d seconds", duration));

    在目標(biāo)方法調(diào)用前首先記錄系統(tǒng)時間,然后通過pjp.proceed()調(diào)用目標(biāo)方法,調(diào)用完之后再次記錄系統(tǒng)時間,即可計算出目標(biāo)方法的耗時。

    處理通知中參數(shù)

    有時我們需要給通知中的方法傳遞目標(biāo)對象的一些信息,比如傳入目標(biāo)業(yè)務(wù)方法的參數(shù)。

    在前面的代碼中我們曾經(jīng)通過@AfterReturning(pointcut = "logPointCut()", returning = "retVal")在通知中獲取目標(biāo)業(yè)務(wù)方法的返回值。獲取參數(shù)的方式則需要使用關(guān)鍵詞是args。

    假設(shè)需要對系統(tǒng)中的accountOperator方法,做Account的驗證,驗證邏輯以切面的方式顯示,示例如下:

    @Before("com.tianmaying.UserService.accountOperator() && args(account,..)") public void validateAccount(Account account) {// ...// 這可以獲取傳入accountOperator中的Account信息 }

    args()中參數(shù)的名稱必須跟切點方法的簽名中(public void validateAccount(Account account))的參數(shù)名稱相同。如果使用切點函數(shù)定義,其中的參數(shù)名稱也必須與通知方法簽名中的參數(shù)完全相同,例如:

    @Pointcut("com.tianmaying.UserService.accountOperator() && args(account,..)") private void accountOperation(Account account) {}@Before("accountOperation(account)") public void validateAccount(Account account) {// ... }

    小節(jié)

    AOP的知識就介紹到這里,更復(fù)雜的場景還需要了解AOP更深入的一些知識,比如:

    • AOP的生成代理的方式
    • 多個切面的順序
    • 更復(fù)雜的參數(shù)類型(如泛型)
    • 使用AspectJ的切面
    • ...

    感興趣的同學(xué)可以繼續(xù)深入學(xué)習(xí),最好的學(xué)習(xí)材料就是Spring的官方文檔。

    天碼營外圍的網(wǎng)站開發(fā)的也基本只使用了我們介紹的這些知識點,可見這些關(guān)鍵知識點足以解決大部分復(fù)雜場景,確實需要用到更高級的特性時,再去參考文檔即可。

    版權(quán)聲明本文由 David創(chuàng)作,轉(zhuǎn)載需署名作者且注明文章出處參考代碼

    要獲取本文的參考代碼,請訪問:?https://www.tianmaying.com/tutorial/spring-aop-point-advice/repo


    from:?https://www.tianmaying.com/tutorial/spring-aop-point-advice

    總結(jié)

    以上是生活随笔為你收集整理的Spring AOP中定义切点(PointCut)和通知(Advice)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲欧美一区在线 | 蜜桃av免费 | 久久久成| 男生和女生靠逼视频 | 男人午夜天堂 | 一级全黄少妇性色生活片 | 丰满岳妇伦在线播放 | 男生和女生一起差差差很痛的视频 | 少妇毛片一区二区三区 | 伊人ab | 最近最新mv字幕观看 | 91爱在线观看 | yy111122少妇光屁股影院 | 国产精品电影网 | 在线亚洲网站 | 一级性生活大片 | 人人插人人草 | 女生喷水视频 | 夜夜草| 日批在线播放 | 久久久激情视频 | 激情欧美一区二区免费视频 | 亚洲黄业| 女~淫辱の触手3d动漫 | 欧美做爰全过程免费看 | www.av在线| 黄色在线观看网址 | 中文字幕在线观看精品 | 夜色精品 | 激情网色 | 日韩va中文 | 欧美乱大交xxxxx潮喷l头像 | 少妇性l交大片7724com | 成年人免费观看网站 | 特级西西444www高清大视频 | 中日韩毛片 | 亚洲精品久久视频 | 综合网视频 | 日韩一区二区视频 | 欧美日韩国产免费 | 天天操操 | 国产一卡二卡三卡四卡 | 丰满熟妇人妻av无码区 | av资源吧首页 | 日本一区二区在线看 | av免费网站在线观看 | 97成人精品视频在线观看 | 亚洲日本网站 | 狠狠干网| 黑丝少妇喷水 | av优选在线观看 | 91九色蝌蚪porny | 草逼视频网站 | 中文字幕av久久 | 2019亚洲男人天堂 | 杂技xxx裸体xxxx欧美 | 久久久久亚洲av成人无码电影 | 福利小视频在线观看 | 中文字幕永久免费 | 精品国产免费视频 | 久久亚洲成人av | 国产的av | 99久久一区 | 国产13页 | 免费在线看黄的网站 | xxxxx在线观看 | 91成人动漫 | 午夜国产免费 | 国产 日韩 欧美 制服丝袜 | 神马久久香蕉 | 正在播放国产精品 | 久久大胆| 欧美操女人 | 日女人网站 | 在线天堂中文字幕 | 91精品国产乱码久久久张津瑜 | 波多野结衣办公室33分钟 | www.777奇米影视 | 天天干b| 亚州欧美在线 | 国产在线观看免费高清 | 亚洲AV无码乱码国产精品色欲 | 99人妻碰碰碰久久久久禁片 | 日本一区二区三区免费电影 | 欧美一级视频免费观看 | 91视频最新入口 | 99伊人 | 麻豆一区二区三区精品视频 | 日韩精品久久久久久久酒店 | 丰满少妇高潮一区二区 | 国产又粗又猛又大爽 | 精品视频中文字幕 | 日韩特黄一级片 | 欧美区二区三区 | 免费在线精品视频 | 成人精品999 | 久草国产在线观看 | 少妇裸体淫交视频免费看高清 | 亚洲欧美激情另类校园 |