【问题标题】:Proxy for a class with no empty constructor using ByteBuddy使用 ByteBuddy 的没有空构造函数的类的代理
【发布时间】:2018-01-25 15:23:00
【问题描述】:

有没有办法使用 ByteBuddy 为没有空构造函数的类创建代理?

这个想法是为给定的具体类型创建一个代理,然后将所有方法重定向到一个处理程序。

这个测试展示了为没有空构造函数的类创建代理的场景,它会抛出一个java.lang.NoSuchMethodException

@Test
public void testProxyCreation_NoDefaultConstructor() throws InstantiationException, IllegalAccessException {

    // setup

    // exercise
    Class<?> dynamicType = new ByteBuddy() //
            .subclass(FooEntity.class) //
            .method(ElementMatchers.named("toString")) //
            .intercept(FixedValue.value("Hello World!")) //
            .make().load(getClass().getClassLoader()).getLoaded();

    // verify
    FooEntity newInstance = (FooEntity) dynamicType.newInstance();
    Assert.assertThat(newInstance.toString(), Matchers.is("Hello World!"));
}

实体:

public class FooEntity {

    private String value;

    public FooEntity(String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

【问题讨论】:

    标签: java byte-buddy dynamic-proxy


    【解决方案1】:

    您调用subclass(FooEntity.class) 意味着Byte Buddy 隐含地模仿了超类定义的所有构造函数。您可以添加自定义 ConstructorStrategy 作为第二个参数来更改此行为。

    但是,JVM 要求任何构造函数最终都调用超级构造函数,而您的代理类仅提供一个具有单个构造函数的构造函数。给定您的代码,您只需提供一个默认参数即可创建代理:

    FooEntity newInstance = (FooEntity) dynamicType
          .getConstuctor(String.class)
          .newInstance(null);
    

    然后将该字段设置为null。或者,您可以使用像 Objenesis 这样的库来实例化类,该库使用 JVM 内部来创建实例,而无需任何构造函数调用。

    【讨论】:

    • 这里的代码只是示例。在实际产品中,代理创建是在工厂内完成的,在该工厂中,代理对象的类在编译时是未知的。我期待像 objenesis 所做的那样,实际上我不希望调用超级构造函数。
    • 哦,我没明白 Objenesis 可以和 ByteBuddy 一起使用。谢谢,问题解决了。
    • 对于下一个版本,我确实添加了一个构造函数策略,只要构造函数没有副作用,就可以解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多