ByteBuddy中的实现方法以更改运行时可发现的字段

问题描述 投票:0回答:1

我正在使用Byte Buddy在运行时创建类bean的接口类,从而减少了大量样板代码。从getter和setter创建字段很简单,但是我想更多地利用Byte Buddy。对于初学者,我不想到处都写这样的代码:

    if (obj.getMax() < obj.getMin()) {
        int temp = obj.getMax();
        obj.setMax(obj.getMin());
        obj.setMin(temp);
    }

    obj.setMax(obj.getMax() + 1);
    int currentMax = getMax();

当我可以做的时候:

    obj.enforceMinMaxOrder();
    int currentMax = obj.incrementAndGetMax();

这里是一个简短的例子。如何使用Byte Buddy使以上两个工作正常进行?大概使用拦截器类,但是我还没有遇到任何修改字段的示例。重要事项:

  • 字段在编译时未知,它们将从方法名称中提取(即“ enforceMinMaxOrder”方法名称使用“ min”和“ max”作为字段名称)
  • [我想避免在Byte Buddy生成类之后使用运行时反射,但是保留对字段或方法的引用并调用它们就可以了。

    DynamicType.Builder<? extends Object> builder = new ByteBuddy().subclass(Object.class);
    builder = builder.implement(MyInterface.class);
    builder = builder.method(
        (isGetter().or(isSetter())))
        .intercept(FieldAccessor.ofBeanProperty());
    for (Method m : MyInterface.class.getMethods()) {
        String methodName = m.getName();
        Class<?> t = m.getReturnType();
        if (t != void.class && methodName.startsWith("get")) {
            String fieldName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
            builder = builder.defineField(fieldName, t, Visibility.PUBLIC);
            builder = builder.method(named(fieldName)).intercept(FieldAccessor.ofField(fieldName));
        }
    }
    
    MyInterface obj = (MyInterface) builder.make().load(BeanUtil.class.getClassLoader()).getLoaded().getConstructor().newInstance();
    
    obj.setMin(10);
    obj.setMax(5);
    
    obj.incrementAndGetMin();
    obj.ensureMinMaxOrder();
    // now, the values should be min=5, max=11
    
java byte-buddy
1个回答
0
投票

我认为您最好的选择是使用Advice,让我们编写代码模板,然后将其内联到生成的类中:

class MinMaxAdvice {
  @Advice.OnMethodExit
  static void minMax(@Min int min, @Max int max) { ... }
}

该方法实现您的代码,并且可以覆盖任何字段值。由于您的解析对方法名敏感,因此您需要为自定义批注@Min@Max添加自己的绑定,请查看Advice.withCustomBinding() API,以了解如何完成此操作。您可以重用已经存在的字段绑定,但是必须以实现此目的的方式找到这些字段。

© www.soinside.com 2019 - 2024. All rights reserved.