[英]How to add setter method for uncertain class fields using ByteBuddy?
According to the official example, generating getter/setter methods for a Field can be done by implementing an interface.按照官方的例子,Field的getter/setter方法可以通过实现一个接口来实现。 But this is when I know exactly which Fields will be added to the Class. My program gets the fields to be added from the database every time, so I need to add getter/setter methods for these fields at runtime.但是这个时候我就知道Class里面到底要添加哪些Field了。我的程序每次都是从数据库中获取要添加的字段,所以我需要在运行时为这些字段添加getter/setter方法。
I define a getter method and assign it as FieldAccessor using intercept method.我定义了一个 getter 方法并使用拦截方法将其分配为 FieldAccessor。 When I define a setter method in the same way and specify it as FieldAccessor, the system throws an exception.当我用同样的方式定义一个setter方法并指定为FieldAccessor时,系统抛出异常。
Here is a simplified example code:这是一个简化的示例代码:
@Data
public class MappingFieldBO {
private String fieldName;
private int maxScore;
public MappingFieldBO() {
}
public MappingFieldBO(String fieldName, int maxScore) {
this.fieldName = fieldName;
this.maxScore = maxScore;
}
}
@Data
public class BaseMappingFieldBO {
private Long id;
}
public class Main {
public static void main(String[] args) {
List<MappingFieldBO> mappingFields = getFromDB();
DynamicType.Builder<BaseMappingFieldBO> builder = new ByteBuddy()
.subclass(BaseMappingFieldBO.class)
.name("io.buyan.dv.console.MappingBean");
// add uncertain fields to class
for (MappingFieldBO mappingField : mappingFields) {
String fieldName = mappingField.getFieldName();
builder = builder.defineField(fieldName, String.class, Visibility.PUBLIC)
// define getter method
.defineMethod(getterName(fieldName), String.class, Visibility.PUBLIC)
.intercept(FieldAccessor.ofField(fieldName))
// define setter method
// throw IllegalArgumentException: Method public void io.buyan.dv.console.MappingBean.setShipping() is no bean accessor
.defineMethod(setterName(fieldName), Void.TYPE, Visibility.PUBLIC)
.intercept(FieldAccessor.ofField(fieldName));
}
Class<? extends BaseMappingFieldBO> clazz = builder.make().load(Thread.currentThread().getContextClassLoader()).getLoaded();
}
private static String setterName(String fieldName) {
return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
}
private static String getterName(String fieldName) {
return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
}
private static List<MappingFieldBO> getFromDB() {
List<MappingFieldBO> list = new ArrayList<>();
list.add(new MappingFieldBO("shipping", 10));
list.add(new MappingFieldBO("deduct", 8));
return list;
}
}
Your setter lacks a parameter of the field's type.您的设置器缺少字段类型的参数。 It returns void
but needs to accept a value of type String
.它返回void
但需要接受String
类型的值。
Byte Buddy has a convenience method for this. Byte Buddy 有一个方便的方法。 Simply add: withProperty(fieldName, String.class)
and everything is setup correctly.只需添加: withProperty(fieldName, String.class)
正确设置所有内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.