我一直在玩ByteBuddy庫一段時間,並發現自己陷入困境。當被測試的類在同一個文件中時,我使用了這個方法(作爲靜態內部類),但現在我已經將邏輯分離爲單獨的文件,它不再有效。如何使用ByteBuddy動態擴展混凝土類
如果有幫助(也許我採取錯誤的做法),我的目標是使輸入類originalClazz
的動態子類和存儲參考originalClazz
Class對象,再加上參考輸入對象original
。 我使用ProxyHandler.execute
方法直接調用original
對象上的方法,並將返回值包裝在代理中(也使用proxyMe
)。
以下塊都在一個Java文件:
private static final String ORIGINAL_OBJECT_FIELD_NAME = "_original_object_";
private static final String ORIGINAL_CLASS_FIELD_NAME = "_original_class_";
public static <T> T proxyMe(final T original, final Class<?> originalClazz) {
if (originalClazz != null && isNotFinal(originalClazz) && hasDefaultConstructor(originalClazz)) {
try {
final Class<?> newSubClass = new ByteBuddy()
.subclass(originalClazz, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.defineField(ORIGINAL_OBJECT_FIELD_NAME, Object.class, Visibility.PUBLIC)
.defineField(ORIGINAL_CLASS_FIELD_NAME, Class.class, Visibility.PUBLIC)
.method(any())
.intercept(to(ProxyHandler.class))
.defineConstructor(Visibility.PUBLIC)
.intercept(MethodCall.invoke(originalClazz.getConstructor()))
.make() // <-- exception thrown here
.load(originalClazz.getClassLoader())
.getLoaded();
final Object result = newSubClass.newInstance();
setField(result, ORIGINAL_OBJECT_FIELD_NAME, original);
setField(result, ORIGINAL_CLASS_FIELD_NAME, originalClazz);
return (T) result;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
return original;
}
public static class ProxyHandler {
@RuntimeType
public static Object execute(
@SuperCall Callable<Object> callable,
@This Object obj,
@Origin Method method,
@AllArguments Object[] arguments
) {
...
}
}
在我的測試類...
@Test
public void makeProxy() throws Exception {
final Foo foo = new Foo(new Bar("str"));
proxyMe(foo, Foo.class);
}
public static class Bar {
private String name;
public Bar() {}
public Bar(final String name) { this.name = name; }
public String getName() { return name; }
}
public static class Foo {
private Bar bar;
public Foo() {}
public Foo(final Bar bar) { this.bar = bar; }
public Bar getBar() { return bar; }
}
拋出異常:
None of [
TargetMethodAnnotationDrivenBinder.Record{
,
candidate=public static java.lang.Object somepackage.Utils$ProxyHandler.execute(
java.util.concurrent.Callable,
java.lang.Object,
java.lang.reflect.Method,
java.lang.Object[]
),
handlers=[
TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
parameterBinder=SuperCall.Binder.INSTANCE,
[email protected]ll(
serializableProxy=false,
nullIfImpossible=false,
fallbackToDefault=true
),
target=java.util.concurrent.Callable arg0,
typing=Assigner.Typing.STATIC
},
TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
parameterBinder=This.Binder.INSTANCE,
[email protected](
optional=false
),
target=java.lang.Object arg1,
typing=Assigner.Typing.STATIC
},
TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
parameterBinder=Origin.Binder.INSTANCE,
[email protected](
cache=true
),
target=java.lang.reflect.Method arg2,
typing=Assigner.Typing.STATIC
},
TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
parameterBinder=AllArguments.Binder.INSTANCE,
annotation=
@net.bytebuddy.implementation.bind.annotation.AllArguments(
value=STRICT,
includeSelf=false
),
target=[Ljava.lang.Object; arg3, typing=Assigner.Typing.STATIC}],
typing=Assigner.Typing.DYNAMIC
}
]
allows for delegation from public somepackage.UtilsTest$Bar somepackage.UtilsTest$Foo.getBar()
你是否從'net.bytebuddy.implementation.bind.annotation.'中導入了攔截器方法的註釋。bytebuddy在多個包中有一些equaly命名的註釋。 –