04 AOP學習之通知參數(shù)

Spring AOP通知參數(shù)

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

1. 使用JoinPoint獲取

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

  1. JoinPoint:提供訪問當前被通知方法的目標對象勤家、代理對象、方法參數(shù)等數(shù)據(jù):

    public interface JoinPoint {
    
        String toString();                  //連接點所在位置的相關(guān)信息  
        String toShortString();             //連接點所在位置的簡短相關(guān)信息  
        String toLongString();              //連接點所在位置的全部相關(guān)信息
        Object getThis();                   //返回AOP代理對象,如果想要使用這個方法的話柳恐,最好使用this連接點伐脖,這樣可以獲得最佳的性能。  
        Object getTarget();                 //返回目標對象,如果想要使用這個方法的話乐设,最好使用target連接點讼庇,這樣可以獲得最佳的性能。
        Object[] getArgs();                 //返回被通知方法參數(shù)列表  
        Signature getSignature();           //返回當前連接點簽名  
        SourceLocation getSourceLocation(); //返回連接點方法所在類文件中的位置  
        String getKind();                   //連接點類型  
        StaticPart getStaticPart();         //返回連接點靜態(tài)部分  
    
        // getKind 方法的返回值
        static String METHOD_EXECUTION = "method-execution";
        static String METHOD_CALL = "method-call";
        static String CONSTRUCTOR_EXECUTION = "constructor-execution";
        static String CONSTRUCTOR_CALL = "constructor-call";
        static String FIELD_GET = "field-get";
        static String FIELD_SET = "field-set";
        static String STATICINITIALIZATION = "staticinitialization";
        static String PREINITIALIZATION = "preinitialization";
        static String INITIALIZATION = "initialization";
        static String EXCEPTION_HANDLER = "exception-handler";
        static String SYNCHRONIZATION_LOCK = "lock";
        static String SYNCHRONIZATION_UNLOCK = "unlock";
        static String ADVICE_EXECUTION = "adviceexecution"; 
    }
    
  2. ProceedingJoinPoint:用于環(huán)繞通知近尚,使用proceed()方法來執(zhí)行目標方法:

public interface ProceedingJoinPoint extends JoinPoint {  
    void set$AroundClosure(AroundClosure arc);              // 這是個內(nèi)部方法蠕啄,不應該直接調(diào)用
    public Object proceed() throws Throwable;               // 執(zhí)行目標函數(shù),以默認的參數(shù)執(zhí)行
    public Object proceed(Object[] args) throws Throwable;  // 執(zhí)行目標函數(shù)戈锻,并傳入所需的參數(shù)
}  
  1. JoinPoint.StaticPart:提供訪問連接點的靜態(tài)部分歼跟,如被通知方法簽名却嗡、連接點類型等:
public interface StaticPart {
    Signature getSignature();           // 返回當前連接點簽名
    SourceLocation getSourceLocation(); // 返回連接點所在資源路徑
    String getKind();                   // 連接點類型
    int getId();                        // 唯一標識 
    String toString();                  // 連接點所在位置的相關(guān)信息
    String toShortString();             // 連接點所在位置的簡短相關(guān)信息
    String toLongString();              // 連接點所在位置的全部相關(guān)信息
}

如果使用該種方式聲明參數(shù),必須放到方法第一個位置上嘹承,如

@Aspect
@Component
public class JoinPointAop {

    // 切點范圍
    @Pointcut("execution(* com.learn.service..IJoinPointService+.*(..))")
    public void pointcut(){ }

    @Before("pointcut()")
    public void before1(JoinPoint jp) {
        System.out.println("---------------@Before1----------------");
        System.out.println(Arrays.toString(jp.getArgs()));
    }

    @Before("pointcut()")
    public void before2(JoinPoint.StaticPart jp) {
        System.out.println("---------------@Before2----------------");
        System.out.println(jp.getSignature());
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("---------------@Around----------------");
        return pjp.proceed();
    }

}

2. 手動指定

通過切入點表達式可以將相應的參數(shù)自動傳遞給通知方法。

在Spring AOP中如庭,除了execution和bean指示符不能傳遞參數(shù)給通知方法叹卷,其他指示符都可以將匹配的相應參數(shù)或?qū)ο笞詣觽鬟f給通知方法。

簡單使用

例:

@Before(value="execution(* com.learn.service..IAppointService+.say(*)) && args(param)", argNames="param") //明確指定了
public void before1(String param) {
    System.out.println("===param:" + param);
}

切入點表達式execution( com.learn.service..IAppointService+.say()) && args(param)**:

  1. 首先execution(* com.learn.service..IAppointService+.say(*))匹配IAppointService接口的實現(xiàn)類的say方法坪它,且有一個任何類型的參數(shù)骤竹;
  2. args(param)將首先查找通知方法上同名的參數(shù),并在方法執(zhí)行時(運行時)匹配傳入的參數(shù)是使用該同名參數(shù)類型往毡,即java.lang.String蒙揣;如果匹配將把該被通知參數(shù)傳遞給通知方法上同名參數(shù)。
    其中argNames可以省略不寫开瞭,但是省略的話如果在class文件中沒生成變量調(diào)試信息是獲取不到方法參數(shù)名字的懒震。
  3. 如果想使用JoinPoint當做參數(shù)的話,也需要在argNames中指定嗤详,如:
    @Before(value="execution(* com.learn.service..IAppointService+.say(*)) && args(param)", argNames="jp, param") //明確指定了
    public void before1(JoinPoint jp, String param) {
        System.out.println("===JoinPoint:" + jp.getKind());
        System.out.println("===param:" + param);
    }
    

組合使用

@Before(value = "pointcut() && args(param) && this(service) && @annotation(secure)", argNames = " jp, param, service, secure")
public void before2(JoinPoint jp, String param, IAppointService service, Secure secure) {
    service.logInfo("==before==");
    System.out.println("===JoinPoint:" + jp.getKind());
    System.out.println("===param:" + param);
    System.out.println("===secure:" + secure.value());
}

也可以使用引用切入點的方式獲取參數(shù):

@Pointcut(value = "args(param)", argNames = "param")
private void pointcut1(String param) {
}

@Pointcut(value = "@annotation(secure)", argNames = "secure")
private void pointcut2(Secure secure) {
}
@Before(value = "pointcut1(param) && pointcut2(secure)", argNames = "jp, param, secure")
public void before3(JoinPoint jp, String param, Secure secure) {
    System.out.println("before3");
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末个扰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子葱色,更是在濱河造成了極大的恐慌递宅,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苍狰,死亡現(xiàn)場離奇詭異办龄,居然都是意外死亡,警方通過查閱死者的電腦和手機淋昭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門俐填,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人响牛,你說我怎么就攤上這事玷禽。” “怎么了呀打?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵矢赁,是天一觀的道長。 經(jīng)常有香客問我贬丛,道長撩银,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任豺憔,我火速辦了婚禮额获,結(jié)果婚禮上够庙,老公的妹妹穿的比我還像新娘。我一直安慰自己抄邀,他們只是感情好耘眨,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著境肾,像睡著了一般剔难。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奥喻,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天偶宫,我揣著相機與錄音,去河邊找鬼环鲤。 笑死纯趋,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的冷离。 我是一名探鬼主播吵冒,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼西剥!你這毒婦竟也來了桦锄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蔫耽,失蹤者是張志新(化名)和其女友劉穎结耀,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匙铡,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡图甜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳖眼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黑毅。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钦讳,靈堂內(nèi)的尸體忽然破棺而出矿瘦,到底是詐尸還是另有隱情,我是刑警寧澤愿卒,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布缚去,位于F島的核電站,受9級特大地震影響琼开,放射性物質(zhì)發(fā)生泄漏易结。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搞动。 院中可真熱鬧躏精,春花似錦、人聲如沸鹦肿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箩溃。三九已至高诺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碾篡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工筏餐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留开泽,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓魁瞪,卻偏偏與公主長得像穆律,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子导俘,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理峦耘,服務(wù)發(fā)現(xiàn),斷路器旅薄,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • Via http://jinnianshilongnian.iteye.com/blog/1415606 http...
    xiaobinZh閱讀 1,558評論 0 52
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法辅髓,類相關(guān)的語法,內(nèi)部類的語法少梁,繼承相關(guān)的語法洛口,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 此刻凯沪,我躺在老家的熱炕上第焰,看冬日的雪花飄飄灑灑從天而降。 雪花是冬天的精靈妨马,落雪的午后挺举,氣溫雖低卻沒有刺...
    魏文晶閱讀 220評論 0 2
  • 1989年湘纵,索尼公司的創(chuàng)始人之一盛田昭夫,斥資48億美元滤淳,對美國哥倫比亞電影公司及關(guān)聯(lián)公司進行并購瞻佛。哥倫比亞電影公...
    劉遠鑫閱讀 987評論 0 1