Advice代碼可以在同一個Java文件中聲明OnMethodEnter
和OnMethodExit
。
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
方法的param1
和param2
被映射到create
方法的所有參數。
開發人員必須確保它們具有相同
的數據類型。
param1
和param2
包含create方法的id
和data
參數的值。
例如,執行此Main1.java之后的檢測過程。
Main1.java包含這行代碼
public class Main1 {
public static void main(String[] args) {
new DataProducer().create(10000, "privateValue");
}
}
第一個和第二個參數的值分別為10000
和privateValue
。
這些值是LogInterceptor.java
的methodStart
方法的param1
和param2
參數的副本
。
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.java
的methodStart
方法的內部使用。
參數沒有映射功能代碼,它只是一個標記注解,表示參數未映射到函數方法的任何參數。
參數:
@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》
喜歡就點個??吧