ByteBuddy(四)—Advice參數

Advice代碼可以在同一個Java文件中聲明OnMethodEnterOnMethodExit
Advice代碼的靜態方法也可以有參數。
例如,LogInterceptor.Java的實現Advice方法中使用了幾個參數

public class LogInterceptor{

    public static Logger logger = Logger.getLogger(LogInterceptor.class.getName());
    
    @OnMethodEnter
    public static void methodStart(int param1, 
                               String param2,
                               @Advice.Origin String mtd,
                               @Advice.Origin("#t") String mtdDeclrType,
                               @Advice.Origin("#m") String mtdName,
                               @Advice.Origin("#d") String mtdDescr,
                               @Advice.Origin("#s") String mtdParamType,
                               @Advice.Origin("#r") String mtdReturn,
                               @Advice.Argument(0) int id,
                               @Advice.Argument(1) String data,
                               @Advice.AllArguments Object[] params,
                               @Advice.This Object thiz,
                               @Advice.FieldValue("recordId") int data1,
                               @Advice.FieldValue("descr") String data2,
                               @Advice.Unused String unusedParam){
        //codeisomitted
    }

    @OnMethodExit
    public static void methodEnd(
                  @Advice.Return(typing=Assigner.Typing.DYNAMIC) Object returnObject){
        //codeisomitted
    }
}

觀察到各種類型的注釋已應用于methodStart方法的參數。
第一個和第二個參數不使用任何注解。
當不使用注解時,這意味著參數被隱式映射到函數方法的參數。
在本例中,DataProducer.java是函數代碼,create方法是函數方法。

public class DataProducer{
    public int recordId = 1;
    private String descr = "privateData";
    public void create(int id, String data){
        System.out.println("create data");
    }
}

因此,methodStart方法的param1param2被映射到create方法的所有參數。
開發人員必須確保它們具有相同的數據類型。
param1param2包含create方法的iddata參數的值。
例如,執行此Main1.java之后的檢測過程。
Main1.java包含這行代碼

public class Main1 {
    public static void main(String[] args) {
        new DataProducer().create(10000, "privateValue");
    }
}

第一個和第二個參數的值分別為10000privateValue。
這些值是LogInterceptor.javamethodStart方法的param1param2參數的副本。

methodStart方法中從第三個參數開始的其余參數是Advice映射參數。

Advice映射參數必須使用Advice注解。

1、@Advice.Origin注解提供函數代碼的函數方法的方法簽名。

參數:
@Advice.Origin String mtd
System.out.println(mtd)
輸出:
public void com.wpixel.bytebuddy.chapter1.DataProducer.create(int, java.lang.String)

2、@Advice.Origin("#t")注解提供了函數代碼的類名,它聲明了create方法。

參數:
@Advice.Origin("#t") String mtdDeclrType
System.out.println(mtdDeclrType);
輸出:
com.wpixel.bytebuddy.chapter1.DataProducer

3、@Advice.Origin("#m")注解提供函數方法的方法名稱。

參數:
@Advice.Origin("#m") String mtdName
System.out.println(mtdName);
輸出:
create

4、@Advice.Origin("#d")注解提供創建方法的方法描述符。

參數:
@Advice.Origin("#d") String mtdDescr
System.out.println(mtdDescr);
輸出:
(ILjava/lang/String;)V

5、@Advice.Origin("#s")注釋提供了一個字符串,該字符串列出了create方法的所有參數的數據類型。

參數:
@Advice.Origin("#s") String mtdParamType
System.out.println(mtdParamType);
輸出:
(int, java.lang.String)

6、@Advice.Origin("#r")注釋提供函數方法返回的數據類型

參數:
@Advice.Origin("#r")String mtdReturn
System.out.println(mtdReturn);
輸出:
void

7、@Advice.Argument注解提供create方法的參數值。

此注解接收一個表示方法參數索引號的整數參數。
例如,Main1.java調用
new DataProducer().create(10000, "testValue");

參數:
@Advice.Argument(0) int id 
@Advice.Argument(1) String value
System.out.println(id+" "+value);
輸出:
10000 testValue

索引0表示第一參數,
索引1表示第二個參數,依此類推

8、@Advice.AllArguments注解以對象數組格式提供create方法的所有參數的值。

例如:Main1.java調用
new DataProducer().create(10000, "testValue");

參數:
@Advice.AllArguments Object[] params
System.out.println(params[0] + " " + params[1]);
輸出:
10000 testValue

9、@Advice.This注釋提供函數代碼的Java對象

參數:
@Advice.This Object thiz
System.out.println(thiz.getClass().getName());
輸出:
com.wpixel.bytebuddy.chapter1.DataProducer

10、@Advice.FieldValue注釋提供函數代碼的實例變量的值。此注釋接受一個表示實例變量名稱的參數。

例如,DataProducer.java聲明了這兩個實例變量:

public int recordId = 1;
private String descr = "privateData";
參數:
@Advice.FieldValue("recordId") int data1
@Advice.FieldValue("descr") String data2
System.out.println(data1 + " " + data2);
輸出:
1 privateData

11、@Advice.Unused注解表示該參數僅用于LogInterceptor.javamethodStart方法的內部使用。

參數沒有映射功能代碼,它只是一個標記注解,表示參數未映射到函數方法的任何參數。

參數:
@Advice.Unused String unusedParam

如果methodStart方法的參數沒有任何注釋,并且參數索引與函數方法的參數索引不匹配,則在maven構建過程中,檢測過程將失敗。

12、@Advice.Return注解僅適用于用@OnMethodExit注解的Advice方法。

@Advice.Return提供create方法的返回值

參數:
@Advice.Return(typing=Assigner.Typing.DYNAMIC) Object returnObject
System.out.println(returnObject);
輸出:
null

觀察到返回值為null,這是因為create方法返回void
當方法返回對象引用時,returnObject應該具有值。
在后面的章節中,有一個示例代碼展示了如何管理返回對象引用的方法。
現在,請注意,當方法返回void時,returnObject的參數值始終為空。

結論
本此介紹如何在Advice方法中創建參數。解釋了各種類型的注解。

  • @Advice.Origin
  • @Advice.Origin("#t")
  • @Advice.Origin("#m")
  • @Advice.Origin("#d")
  • @Advice.Origin("#s")
  • @Advice.Origin("#r")
  • @Advice.Argument
  • @Advice.AllArgument
  • @Advice.This
  • @Advice.FieldValue
  • @Advice.Unused
  • @Advice.Return

bytebuddy書籍《Java Interceptor Development with ByteBuddy: Fundamental》

----END----

喜歡就點個??吧

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,537評論 1 92
  • IoC 容器 Bean 的作用域 自定義作用域實現 org.springframework.beans.facto...
    Hsinwong閱讀 2,502評論 0 7
  • 一、重點知識 ioc的實現原理1、創建一個工廠類2、用xml解析得到xml文件中的全路徑名3、通過反射的方式創建對...
    一花一世界yu閱讀 387評論 0 2
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,890評論 18 139
  • 一、 AOP 簡介 1.1 什么是 AOP AOP (Aspect Orient Programming),直譯過...
    GaaraZ閱讀 255評論 0 0