我正在使用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使以上两个工作正常进行?大概使用拦截器类,但是我还没有遇到任何修改字段的示例。重要事项:
[我想避免在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
我认为您最好的选择是使用Advice
,让我们编写代码模板,然后将其内联到生成的类中:
class MinMaxAdvice {
@Advice.OnMethodExit
static void minMax(@Min int min, @Max int max) { ... }
}
该方法实现您的代码,并且可以覆盖任何字段值。由于您的解析对方法名敏感,因此您需要为自定义批注@Min
和@Max
添加自己的绑定,请查看Advice.withCustomBinding()
API,以了解如何完成此操作。您可以重用已经存在的字段绑定,但是必须以实现此目的的方式找到这些字段。