Java 如何使用ByteBuddy动态扩展具体类

Java 如何使用ByteBuddy动态扩展具体类,java,byte-buddy,dynamic-proxy,Java,Byte Buddy,Dynamic Proxy,我已经玩了一段时间的ByteBuddy图书馆,我发现自己被卡住了。当被测试的类位于同一个文件中(作为静态内部类)时,这个方法可以工作,但是现在我已经将逻辑分离到一个单独的文件中,它不再工作了 如果有帮助的话(也许我采取了错误的方法),我的目标是创建输入类originalClazz的动态子类,并存储对originalClazz类对象的引用,以及对输入对象original的引用。 我使用ProxyHandler.execute方法直接调用original对象上的方法,并将返回值包装在代理中(也使用p

我已经玩了一段时间的ByteBuddy图书馆,我发现自己被卡住了。当被测试的类位于同一个文件中(作为静态内部类)时,这个方法可以工作,但是现在我已经将逻辑分离到一个单独的文件中,它不再工作了

如果有帮助的话(也许我采取了错误的方法),我的目标是创建输入类
originalClazz
的动态子类,并存储对
originalClazz
类对象的引用,以及对输入对象
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
    ) {
        ...
    }
}
引发异常:

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,
        annotation=@net.bytebuddy.implementation.bind.annotation.SuperCall(
          serializableProxy=false,
          nullIfImpossible=false,
          fallbackToDefault=true
        ),
        target=java.util.concurrent.Callable arg0,
        typing=Assigner.Typing.STATIC
      },
      TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
        parameterBinder=This.Binder.INSTANCE,
        annotation=@net.bytebuddy.implementation.bind.annotation.This(
          optional=false
        ),
        target=java.lang.Object arg1,
        typing=Assigner.Typing.STATIC
      },
      TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
        parameterBinder=Origin.Binder.INSTANCE,
        annotation=@net.bytebuddy.implementation.bind.annotation.Origin(
          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()

ProxyHandler
类似乎是
private
。这可能意味着它对插入指令的代码不可见,因此不能作为处理程序调用。公开课堂,一切都应按预期进行。

感谢您的快速回复。不幸的是,这并没有解决问题。将所有内容公开只是为了确保,仍然没有运气-相同的错误:(您是否从
net.bytebuddy.implementation.bind.annotation导入了拦截器方法的注释。
bytebuddy在多个包中有一些同名注释。
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,
        annotation=@net.bytebuddy.implementation.bind.annotation.SuperCall(
          serializableProxy=false,
          nullIfImpossible=false,
          fallbackToDefault=true
        ),
        target=java.util.concurrent.Callable arg0,
        typing=Assigner.Typing.STATIC
      },
      TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
        parameterBinder=This.Binder.INSTANCE,
        annotation=@net.bytebuddy.implementation.bind.annotation.This(
          optional=false
        ),
        target=java.lang.Object arg1,
        typing=Assigner.Typing.STATIC
      },
      TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound{
        parameterBinder=Origin.Binder.INSTANCE,
        annotation=@net.bytebuddy.implementation.bind.annotation.Origin(
          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()