[英]How can we access methods generated by ByteBuddy in compilation time?
我寫了這個例子:
E someCreateMethod(Class<E> clazz) {
Class<? extends E> dynamicType = new ByteBuddy()
.subclass(clazz)
.name("NewEntity")
.method(named("getNumber"))
.intercept(FixedValue.value(100))
.defineField("stringVal", String.class, Visibility.PRIVATE)
.defineMethod("getStringVal", String.class, Visibility.PUBLIC)
.intercept(FieldAccessor.ofBeanProperty())
.make()
.load(clazz.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
return dynamicType.newInstance();
}
我想用它來獲取重新定義的number
屬性:
Integer num = someCreateMethod(EntityExample.class).getNumber(); //(1)
或獲取新定義的stringVal
屬性:
String sVal = someCreateMethod(EntityExample.class).getStringVal(); //(2)
我的問題是(1)效果很好,而(2)效果不好。 我收到以下錯誤:
Error:(40, 67) java: cannot find symbol
symbol: method getStringVal()
另外,是否可以對動態生成的類執行以下操作:
NewEntity newEntity = someCreateMethod(EntityExample.class);
Integer num = newEntity.getNumber();
String sVal = newEntity.getStringVal();
?
編輯:感謝您的幫助,此示例是我第一次嘗試使用ByteBuddy庫。 我發現defineMethod
實際上定義了接口方法的實現,而不僅僅是在類中添加隨機方法。 所以我決定在這里解釋我到底要完成什么。
對於E類中的每個Date
屬性,我想再添加兩個字段(以及它們各自的getter和setters),比如說(atribute name)InitialDate
和(atribute name)FinalDate
,以便我可以對中的每個日期使用間隔函數E
我想知道是否可以使用代碼生成來添加這些方法,而不必為每個E
創建子類。
PS: E
不能更改,它屬於舊模塊。
PS2:我不知道每個實體E
中將有多少個日期屬性,但是將使用約定(例如__FisrtDay
, __LastDay
)來創建新的服裝和方法,如下所示:
NewA a = eb.create(A.class);
a.getDeadLine(); //inherited
a.getDeadLineFirstDay(); //added
a.getDeadLineLastDay(); //added
NewA b = eb.create(B.class);
b.getBirthday(); //inherited
b.getBirthdayFirstDay(); //added
b.getBirthdayLastDay(); //added
b.getAnniversary(); //inherited
b.getAnniversaryFirstDay(); //added
b.getAnniversaryLastDay(); //added
PS3:我嘗試使用ByteBuddy甚至完成什么? 還有另一種方法嗎?
PS4:我的編輯應該是一個新問題嗎?
您需要E成為包含要嘗試調用的方法的超類/或接口-您將無法解析E上不存在的子類型方法。
這不是ByteBuddy的問題,這不是類設計的問題-您應該將要生成的功能設計和分組為可抽象的部分,以便可以通過在編譯時有意義的類型來公開它。
例如,我們可以使用超類型'ValueProvider',然后使用ByteBuddy定義IntConstantProvider。
public interface ValueProvider<T> {
public T getValue();
}
Class<? extends ValueProvider<Integer>> dynamicType = new ByteBuddy()
.subclass(clazz)
.name("ConstantIntProvider")
.method(named("getValue"))
.intercept(FixedValue.value(100))
// etc.
您的原型具有3個單獨的功能(如果我們將非引用私有字段視為某些預期行為的殘根),則沒有明顯的抽象來包含它們。 最好將其設計為3個簡單的原子行為,對於這些行為,抽象是顯而易見的。
您可以使用反射在任意動態定義的類上查找任意方法,但這對於編碼或設計POV而言並沒有真正的意義(您的代碼如何知道要調用的方法?如果知道,為什么不使用類型來表達出來嗎?)也不是很出色。
按照問題進行編輯 -Java Bean屬性是通過反射起作用的,因此從已知屬性中查找“相關屬性”(例如“第一/最后日期”)的例子並非不合理。
但是,可以考慮使用DateInterval(FirstDate,LastDate)類,以便每個基本屬性僅需要一個補充屬性。
正如Thomas所指出的,Byte Buddy在運行時生成類,以使您的編譯器無法在編譯期間驗證它們的存在。
您可以做的是在構建時應用代碼生成。 如果您的EntityExample.class
存在於特定模塊中,則可以使用Byte Buddy Maven或Gradle插件來增強此模塊,然后在增強后允許編譯器驗證其存在。
您還可以做的是定義接口,例如
interface StringVal {
String getStringVal();
}
您可以要求Byte Buddy在您的子類中實現,如果您將子類表示為此接口,則允許編譯器驗證方法的存在。
除此之外,您的編譯器完全按照預期的方式運行:告訴您正在調用的方法(當時不存在)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.