2017-05-29 5 views
0

私はしばらくの間、ByteBuddyライブラリを使って遊んできました。テストされたクラスが静的な内部クラスと同じファイル内にあるときにこのメソッドを動作させましたが、ロジックを別のファイルに分けたので、もはや動作しません。ByteBuddyでコンクリートクラスを動的に拡張する方法

ことができます(そして多分私は間違ったアプローチを取っている)場合は、私の目標は、入力クラスoriginalClazzの動的なサブクラスを作成し、originalClazz Classオブジェクトへの参照、プラス入力オブジェクトへの参照を格納することですoriginalProxyHandler.executeメソッドを使用して、originalオブジェクトのメソッドを直接呼び出し、戻り値をプロキシでラップします(proxyMeも使用します)。

次のブロックがすべて1つの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.your 'からインポートしましたか?bytebuddyには、複数のパッケージに等号アノテーションがいくつかあります。 –

答えて

0

ProxyHandlerクラスが表示されますをprivateとする。これはおそらく、インスツルメントされたコードには表示されず、したがってハンドラとして呼び出すことができないことを意味します。クラスをパブリックにすると、すべてが期待どおりに動作するはずです。

+0

迅速な対応に感謝します。残念ながら、これは問題を解決しませんでした。すべてのものを公開して、確かに運が良かった - 同じエラー:( –

関連する問題