[英]ByteBuddy: Use new defined field in intercept during construction of class
我正在看別人的一些ByteBuddy代碼。 他使用ByteBuddy生成運行時子類,這些子類用作代理以將其運行時的一些管理代碼實現為特定對象。
Class<? extends T> newSubClass = new ByteBuddy(ClassFileVersion.ofThisVm())
.subclass(classType)
.defineField("_core", Object.class, Visibility.PUBLIC) //<---
.method(ElementMatchers.isDeclaredBy(classType))
.intercept(InvocationHandlerAdapter.of((proxy, method, m_args) -> {
//TODO: Need to replace core with _core as core is a function argument and will make it bound
return proxyHandler(core, method, m_args); //<--
}))
.make()
.load(roleType.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
T proxy = ReflectionHelper.newInstance(newSubClass, args);
newSubClass.getField("_core").set(proxy, core);
為了不將core
對象直接綁定到lambda中,我想使用新定義的字段_core
以便我可以重用生成的類(而不是在每次調用函數時重新生成它)。 有沒有辦法做到這一點?
提前致謝。
您可以像定義方法一樣定義自定義構造函數。 定義構造函數的一個重要點是,您需要另一個構造函數調用作為其第一條指令。 您可以使用MethodCall::invoke
調用構造函數,該方法可以與FieldAccessor::ofField
結合使用。
這樣,您可以類似於以下內容來定義您的類:
new ByteBuddy(ClassFileVersion.ofThisVm())
.subclass(classType, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.defineConstructor(Visibility.PUBLIC)
.withParameter(InvocationHandler.class)
.intercept(MethodCall.invoke(classType.getDeclaredConstructor())
.andThen(FieldAccessor.ofField("_core").setsArgumentAt(0)))
.defineField("_core", InvocationHandler.class, Visibility.PUBLIC)
.method(ElementMatchers.isDeclaredBy(classType))
.intercept(InvocationHandlerAdapter.toField("_core"))
.make();
這樣,您可以為每個實例設置自定義InvocationHandler
。 如果您只想將狀態存儲在_core
字段中,並從攔截器訪問此字段,請查看MethodDelegation
:
new ByteBuddy(ClassFileVersion.ofThisVm())
.subclass(classType, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.defineConstructor(Visibility.PUBLIC)
.withParameter(Object.class)
.intercept(MethodCall.invoke(classType.getDeclaredConstructor())
.andThen(FieldAccessor.ofField("_core").setsArgumentAt(0)))
.defineField("_core", Object.class, Visibility.PUBLIC)
.method(ElementMatchers.isDeclaredBy(classType))
.intercept(MethodDelegation.to(MyHandler.class))
.make();
public class MyHandler {
@RuntimeType
public static Object intercept(@FieldValue("_core") Object value) { ... }
}
您可能需要的其他注釋是@This
, @AllArguments
, @Origin
和@SuperCall
。 您需要的越少,代理的效率就越高。 特別是@AllArguments
由於其分配要求而非常昂貴。
請注意,在這種情況下,僅在超級構造函數調用之后設置您的字段。 此外,您假定超級類型中包含默認構造函數。 另外,您可以實現自定義的ConstructorStrategy
。
至於緩存,請看一下Byte Buddy的TypeCache
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.