简体   繁体   English

在使用 ByteBuddy 创建的构造函数中创建自定义代码

[英]Create custom code in a constructor created with ByteBuddy

I'm new with byteBudd and doing first test to learn about it I got a solution for a "problem" but I would like to improve it.我是 byteBudd 的新手,正在做第一次测试以了解它我得到了一个“问题”的解决方案,但我想改进它。 I would like to generate a this code:我想生成一个这样的代码:

public class A {
  private String value;
  public A(){}
  public A(Map<String, Object> p){
    this.value=p.get("value");
  }
  //getter and setter
}

I made it work using MethodDelegation.to and use of reflection with this code我使用 MethodDelegation.to 使其工作并使用此代码进行反射

@Test
    public void withReflection() throws Exception {


        DynamicType.Builder builder = new ByteBuddy()
                .subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
                .name("cat.altimiras.dynamic.AAA") //must be same package
                .defineField("value", String.class, Visibility.PRIVATE)
                .defineMethod("getValue", String.class, Visibility.PUBLIC)
                .intercept(FieldAccessor.ofBeanProperty())
                .defineMethod("setValue", void.class, Visibility.PUBLIC)
                .withParameters(String.class)
                .intercept(FieldAccessor.ofBeanProperty())
                .defineConstructor(Visibility.PUBLIC)
                .intercept(MethodCall.invoke(Object.class.getDeclaredConstructor()))
                .defineConstructor(Visibility.PUBLIC)
                .withParameter(Map.class)
                .intercept(
                        MethodCall.invoke(Object.class.getDeclaredConstructor())
                                .andThen(
                                    MethodDelegation.to(
                                            new Object() {
                                                public void assign(@RuntimeType Map<String, Object> value, @This Object o) throws Exception {
                                                    Field f = o.getClass().getDeclaredField("value");
                                                    f.setAccessible(true);
                                                    f.set(o, value.get("value")); // Reflection
                                                }
                                            }
                                    )
                                )
                );

        Class cl = builder.make().load(this.getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded();

        Map<String, String> p = new HashMap<>();
        p.put("value", "lala");

        Object o = cl.getConstructor(Map.class).newInstance(p);

        Assert.assertEquals("lala", o.getClass().getDeclaredMethod("getValue").invoke(o));

This is working but I don't like because : 1 - I would like to avoid the use of reflection 2 - "A" can't not be to a random package "xyzA" for instance这是有效的,但我不喜欢,因为: 1 - 我想避免使用反射 2 - 例如,“A”不能不是随机包“xyzA”

Do you know if this is possible?你知道这是否可能? And how to do it?以及怎么做?

Thanks in advance提前致谢

You are using a method delegation to an anonymous type which is defined as package-private by the Java compiler.您正在使用匿名类型的方法委托,该类型被 Java 编译器定义为包私有。 If you define a named, public class, you can invoke the delegator from any package.如果定义了一个命名的公共类,则可以从任何包中调用委托者。

Also, use the @FieldValue annotation rather than reflection to access the field in question.此外,使用@FieldValue注释而不是反射来访问相关字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM