【问题标题】:How do I build an concrete implementation of a Java Class from an interface using Byte-Buddy?如何使用 Byte-Buddy 从接口构建 Java 类的具体实现?
【发布时间】:2016-04-12 01:56:00
【问题描述】:

我有一个界面,假设它看起来像这样。

public interface TestObject {
    String getString();

    Long getLong();
}

我想使用 ByteBuddy 实际构建这个对象的具体实现。

这是我尝试过的。

public class Runme {

    public static void main(String[] args) {
        ByteBuddy bb = new ByteBuddy();

        Class<?> clz = bb
                .subclass(TestObject.class)
      .method(any()).intercept(MethodDelegation.to(Interceptor.class))
            .make()
            .load(Object.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded();

    try {
        Object test = clz.newInstance();

    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

}

public class Interceptor {

    public Object intercept(@Origin String method, @AllArguments Object[] args) throws Throwable {
        System.out.println("I have intercepted a call");

        return "Hello";

    }

}

}

我收到此错误

Exception in thread "main" java.lang.IllegalArgumentException: None of [] allows for delegation from public boolean java.lang.Object.equals(java.lang.Object)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.process(MethodDelegationBinder.java:881)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1218)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:510)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:444)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:3193)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1481)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:234)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:2177)
at com.meta.testbytebuddy.Runme.main(Runme.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

我做错了什么++..如果我想实现多个接口怎么办?

我将 ByteBuddy 用于代码生成目的。

【问题讨论】:

    标签: java bytecode byte-buddy


    【解决方案1】:

    问题是您通过MethodDelegation.to(Interceptor.class) 委托拦截器的静态方法,而拦截器类只声明了非静态成员。您可以将拦截器方法声明为static,也可以委托给实例而不是委托给类。我认为前一种方法会更合适。

    但是,仅此一项仍然行不通。您正在从拦截器返回 Object 类型,同时,您正在拦截 any() 方法。这包括TestObject 接口的方法,也包括隐式超类Object 声明的方法。您可以按如下方式定义拦截器以使您的类编译,但是 Byte Buddy 会将返回类型转换为每个方法的返回类型,这将导致 ClassCastException

    public class Interceptor {
      @RuntimeType
      public static Object intercept(@Origin String method, @AllArguments Object[] args) {
        System.out.println("I have intercepted a call");
        return "Hello";
      }
    }
    

    【讨论】:

    • 非常感谢,再问一个问题,多接口怎么实现的?
    • 你可以看看API文档:动态类型构建器有一个实现方法。
    • 感谢您的澄清。遇到类似的问题,通过更改解决了它:.intercept(MethodDelegation.to(MyRecyclerViewAdapterInterceptor.class)).intercept(MethodDelegation.to(new MyRecyclerViewAdapterInterceptor())) ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    相关资源
    最近更新 更多