我们有一个POJO,它会自动生成约60个属性。这是通过avro 1.4生成的,其中不包括getter / setter。
我们用来在对象之间提供简单转换的库需要类似于getter / setter的方法才能正常工作。
是否有一种无需手动覆盖POJO即可手动复制所有getter / setter的方法来复制getter / setter的方法?
public class BigGeneratedPojo {
public String firstField;
public int secondField;
...
public ComplexObject nthField;
}
public class OtherObject {
private String reprOfFirstFieldFromOtherObject;
private ComplexObject reprOfFirstFieldFromOtherObject;
public String getReprOfFirstFieldFromOtherObject() { ... standard impl ... };
public void setReprOfFirstFieldFromOtherObject() { ... standard impl ... };
}
人们希望编写如下代码:
Mapper<BigGeneratedPojo, OtherObject> mapper =
MagicalMapperLibrary.mapperBuilder(BigGeneratedPojo.class, OtherObject.class)
.from(BigGeneratedPojo::getFirstField).to(OtherObject::reprOfFirstFieldFromOtherObject)
.build();
BigGeneratedPojo pojo = new BigGeneratedPojo();
pojo.firstField = "test";
OtherObject mappedOtherObj = mapper.map(pojo);
assertEquals(mappedOtherObj.getReprOfFirstFieldFromOtherObject(), "test");
答案 0 :(得分:10)
Project Lombok提供了@Getter和@Setter批注,可在类级别使用它们自动生成getter和setter方法。
Lombok还具有生成equals和哈希码方法的功能。
或者您也可以使用@Data
,具体取决于lombok网站:
@Data现在在一起:@ ToString,@ EqualsAndHashCode, 在所有字段上使用@Getter,在所有非最终字段上使用@Setter,以及 @RequiredArgsConstructor!
@Data
public class BigGeneratedPojo {
public String firstField;
public int secondField;
...
public ComplexObject nthField;
}
答案 1 :(得分:7)
例如,您可以尝试使用BitBuddy:https://bytebuddy.net/
动态地生成代理bean。下面的示例显示如何代理方法的属性字段。请注意,这只是一个示例,很可能您可能需要包装它并使用反射添加一些动态,但是如果您想动态扩展代码,我认为这是一个非常有趣的选择。
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.jar.asm.Opcodes;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class M1 {
public static class PojoBase {
int property;
String strProp;
}
public static class Intereptor {
private final String fieldName;
private final PojoBase pojo;
public Intereptor(PojoBase pojo, String fieldName) {
this.pojo = pojo;
this.fieldName = fieldName;
}
@RuntimeType
public Object intercept(@RuntimeType Object value) throws NoSuchFieldException, IllegalAccessException {
Field field = pojo.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(pojo, value);
return value;
}
}
public static void main(String... args) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
PojoBase origBean = new PojoBase();
PojoBase destBean = new PojoBase();
origBean.property = 555666;
origBean.strProp = "FooBar";
DynamicType.Builder<Object> stub = new ByteBuddy()
.subclass(Object.class);
DynamicType.Builder.MethodDefinition.ReceiverTypeDefinition<Object> dynamic = stub.defineMethod("getProperty", Integer.TYPE, Opcodes.ACC_PUBLIC).intercept(FixedValue.value(origBean.property))
.defineMethod("setProperty", Void.TYPE, Opcodes.ACC_PUBLIC).withParameters(Integer.TYPE).intercept(MethodDelegation.to(new Intereptor(destBean, "property")))
.defineMethod("getStrProp", String.class, Opcodes.ACC_PUBLIC).intercept(FixedValue.value(origBean.strProp))
.defineMethod("setStrProp", Void.TYPE, Opcodes.ACC_PUBLIC).withParameters(String.class).intercept(MethodDelegation.to(new Intereptor(destBean, "strProp")));
Class<?> dynamicType = dynamic.make()
.load(M1.class.getClassLoader())
.getLoaded();
Object readerObject = dynamicType.newInstance();
Object writterObject = dynamicType.newInstance();
BeanUtils.copyProperties(readerObject, writterObject);
System.out.println("Out property:" + destBean.property);
System.out.println("Out strProp:" + destBean.property);
}
}
答案 2 :(得分:4)
鉴于您的约束,我将添加另一个代码生成步骤。如何实现它完全取决于您的构建系统(Maven / Gradle /其他),但是JavaParser或Roaster将允许您解析BigGeneratedPojo.java
并使用所需的getters /创建一个子类。设置者,并且BigGeneratedPojo
发生更改时,构建系统应自动更新它。
答案 3 :(得分:1)
像Eclipse和STS这样的IDE提供了添加getter / setter方法的选项。我们可以使用这些选项来创建setters / getters方法
答案 4 :(得分:1)
我建议使用反射从类中获取公共字段,并使用您自己的Java程序创建getter和setter,如下所示。以下面的类为例。
import java.lang.reflect.Field;
import java.util.Arrays;
class TestClass {
private int value;
private String name;
private boolean flag;
}
public class GetterSetterGenerator {
public static void main(String[] args) {
try {
GetterSetterGenerator gt = new GetterSetterGenerator();
StringBuffer sb = new StringBuffer();
Class<?> c = Class.forName("TestClass");
// Getting fields of the class
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
String fieldName = f.getName();
String fieldType = f.getType().getSimpleName();
gt.createSetter(fieldName, fieldType, sb);
gt.createGetter(fieldName, fieldType, sb);
}
System.out.println("" + sb.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void createSetter(String fieldName, String fieldType, StringBuffer setter) {
setter.append("public void").append(" set");
setter.append(getFieldName(fieldName));
setter.append("(" + fieldType + " " + fieldName + ") {");
setter.append("\n\t this." + fieldName + " = " + fieldName + ";");
setter.append("\n" + "}" + "\n");
}
private void createGetter(String fieldName, String fieldType, StringBuffer getter) {
// for boolean field method starts with "is" otherwise with "get"
getter.append("public " + fieldType).append((fieldType.equals("boolean") ? " is" : " get") + getFieldName(fieldName) + " () { ");
getter.append("\n\treturn " + fieldName + ";");
getter.append("\n" + "}" + "\n");
}
private String getFieldName(String fieldName) {
return fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1, fieldName.length());
}
}
代码采用from here-稍加修改,以避免不必要的System.out
。您可以轻松地通过main
函数创建文件,并将获取器和设置器放在那里。
您也可以通过running it here检查程序。希望对您有所帮助。
答案 5 :(得分:1)
您可以使用Lombok。是易于使用和实施。它将在.class文件后期编译中创建getter和setter。它还可以使代码看起来更简洁。
@Getter @Setter @NoArgsConstructor
public class User implements Serializable {
private @Id Long id;
private String firstName;
private String lastName;
private int age;
public User(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}