2017-05-29 37 views
0

我一直在玩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() 
+0

你是否從'net.bytebuddy.implementation.bind.annotation.'中導入了攔截器方法的註釋。bytebuddy在多個包中有一些equaly命名的註釋。 –

回答

0

出現ProxyHandler類爲private。這可能意味着它對於你的檢測代碼是不可見的,因此不能作爲處理程序調用。使課堂公開,一切都應按預期工作。

+0

感謝您的快速響應。不幸的是,這並沒有解決問題。一切公開只是爲了確保,仍然沒有運氣 - 同樣的錯誤:( –