国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 分析java 中AspectJ切面執(zhí)行兩次的原因

分析java 中AspectJ切面執(zhí)行兩次的原因

2020-12-26 15:27u011116672 Java教程

這篇文章主要介紹了分析java 中AspectJ切面執(zhí)行兩次的原因的相關資料,希望通過本能幫助到大家,需要的朋友可以參考下

分析java 中aspectj切面執(zhí)行兩次的原因

背景

轉眼之間,發(fā)現(xiàn)博客已經(jīng)將近半年沒更新了,甚是慚愧。話不多說,正如標題所言,最近在使用aspectj的時候,發(fā)現(xiàn)攔截器(aop切面)執(zhí)行了兩次了。我們知道,aspectj是aop的一種解決方案,本質上是通過代理類在目標方法執(zhí)行通知(advice),然后由代理類再去調用目標方法。所以,從這點講,攔截器應該只會執(zhí)行一次。但是在測試的時候發(fā)現(xiàn)攔截器執(zhí)行了兩次。

問題重現(xiàn)

既然問題已經(jīng)明了,那么可以通過代碼簡單重現(xiàn)這個問題,從而更深層次分析到底是什么原因導致的。

定義一個注解:

?
1
2
3
4
5
6
7
8
9
package com.rhwayfun.aspect;
 
import java.lang.annotation.*;
 
@target({elementtype.method})
@retention(retentionpolicy.class)
@documented
public @interface statsservice {
}

為該注解定義切面:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.rhwayfun.aspect;
 
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.around;
import org.aspectj.lang.annotation.aspect;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
@aspect
public class statsserviceinterceptor {
 
  private static logger log = loggerfactory.getlogger(statsserviceinterceptor.class);
 
  @around("@annotation(statsservice)")
  public object invoke(proceedingjoinpoint pjp) {
    try {
      log.info("before invoke target.");
      return pjp.proceed();
    } catch (throwable e) {
      log.error("invoke occurs error:", e);
      return null;
    } finally {
      log.info("after invoke target.");
    }
  }
 
}

方法測試:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.rhwayfun;
 
import com.rhwayfun.aspect.statsservice;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
 
import java.time.localdatetime;
 
public class aspecttest {
 
  private static logger log = loggerfactory.getlogger(aspecttest.class);
 
  public static void main(string[] args) {
    aspecttest.print();
  }
 
  @statsservice
  public static void print(){
    log.info("now: {}", localdatetime.now());
  }
}

輸出結果:

分析java 中AspectJ切面執(zhí)行兩次的原因

debug分析

由于是靜態(tài)織入,所以可以通過反編譯工具查看編譯后的文件,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class aspecttest
{
  private static logger log;
  private static final /* synthetic */ joinpoint$staticpart ajc$tjp_0;
  private static final /* synthetic */ joinpoint$staticpart ajc$tjp_1;
 
  public static void main(final string[] args) {
    statsserviceinterceptor.aspectof().invoke(((aroundclosure)new aspecttest$ajcclosure1(new object[] { factory.makejp(aspecttest.ajc$tjp_0, (object)null, (object)null) })).linkclosureandjoinpoint(0));
  }
 
  @statsservice
  public static void print() {
    statsserviceinterceptor.aspectof().invoke(((aroundclosure)new aspecttest$ajcclosure3(new object[] { factory.makejp(aspecttest.ajc$tjp_1, (object)null, (object)null) })).linkclosureandjoinpoint(65536));
  }
 
  static {
    ajc$preclinit();
    aspecttest.log = loggerfactory.getlogger((class)aspecttest.class);
  }
 
  private static /* synthetic */ void ajc$preclinit() {
    final factory factory = new factory("aspecttest.java", (class)aspecttest.class);
    ajc$tjp_0 = factory.makesjp("method-call", (signature)factory.makemethodsig("9", "print", "com.rhwayfun.aspecttest", "", "", "", "void"), 17);
    ajc$tjp_1 = factory.makesjp("method-execution", (signature)factory.makemethodsig("9", "print", "com.rhwayfun.aspecttest", "", "", "", "void"), 22);
  }
}

請注意兩個連接點:ajc$tjp_0和ajc$tjp_1,這兩個連接點是產(chǎn)生兩次調用的關鍵,問題注解明明是加上print()方法上的,為什么main()方法也被注入了通知呢?正因為main()方法也織入了通知,所以就形成了a call b, b call print()的調用鏈,有兩次method-call,一次method-execution,method-execution才是我們的目標方法print(),所以我們才看到了兩次輸出。

?
1
method-call和method-execution都是連接點proceedingjoinpoint的kind屬性

其實,這屬于ajc編譯器的一個bug,詳見ajc-bug

所以,到這一步,問題就很清晰了,因為ajc編輯器的bug,導致了在main方法中也織入了通知,所以在執(zhí)行的時候,輸出了兩次日志。

解決方法

方案一

因為兩次調用的kind屬性不一樣,所以可以通過kind屬性來判斷時候調用切面。這樣顯得不優(yōu)雅,而且如果切面有更多的邏輯的話,需要加各種if-else的判斷,所以不推薦。

方法二

更優(yōu)雅的方案是修改@around("@annotation(statsservice)")的邏輯,改為@around("execution(* *(..)) && @annotation(statsservice)")。

重新運行上面的測試類,結果如下:

分析java 中AspectJ切面執(zhí)行兩次的原因

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/u011116672/article/details/63685340

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 在线一区观看 | 欧美视频精品在线 | 成人小视频在线观看 | 国产男人天堂 | 九九porny88av | 黄站免费 | 黄色影片免费在线观看 | 色播久久| 一呦二呦三呦国产精品 | 久久99精品国产麻豆婷婷 | av中文字幕免费在线观看 | 久久精品亚洲精品 | 久久久极品 | 免费观看黄色12片一级视频 | 中文字幕在线视频一区 | 日韩免费在线观看视频 | 91精品国产综合久久小仙女陆萱萱 | 一区二区三区 在线 | 国产精品影院在线观看 | 黑人xxx视频 | 超碰最新网址 | 久久久久久亚洲一区二区三区蜜臀 | 亚洲国产中文字幕 | 久久99精品久久久 | 国产黄色免费看 | 看a网址| 亚洲欧美v国产一区二区 | 日韩欧美一区二区三区 | 日韩视频在线播放 | 色嫩紧中文字幕在线 | 天堂一区二区三区在线 | 久久久久高清 | 国产真实精品久久二三区 | 日本a v在线播放 | 理伦影院| 亚洲视频播放 | 欧美国产视频一区 | 日韩欧美成人影院 | 日本一区二区三区中文字幕 | 中文字幕一区二区三区精彩视频 | 日韩精品一区二区三区 |