简体   繁体   English

为 POJO 中的公共属性复制 getter/setter 的方法

[英]Way to replicate getters/setters for public properties in a POJO

We have a POJO that is auto-generated with ~60 properties.我们有一个自动生成的具有大约 60 个属性的 POJO。 This is generated with avro 1.4, which does not include getters/setters.这是使用 avro 1.4 生成的,它不包括 getter/setter。

A library that we use to provide simple transformations between objects requires getter/setter-like methods in order to properly work.我们用来在对象之间提供简单转换的库需要类似 getter/setter 的方法才能正常工作。

Is there a way to replicate getters/setters without having to manually override the POJO and create all of the getters/setters manually?有没有一种方法可以复制 getter/setter 而不必手动覆盖 POJO 并手动创建所有 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 ... };
}

the desire is to write code that looks like:希望编写如下代码:

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");

Project Lombok provides @Getter and @Setter annotations which can be used at class level to generate getter and setter methods automatically. Project Lombok提供了 @Getter 和 @Setter 注释,可以在 class 级别使用来自动生成 getter 和 setter 方法。

Lombok also has the capability to generate equals and hashcode methods. Lombok 还具有生成 equals 和 hashcode 方法的能力。

Or you can use the @Data which is according to lombok website:或者您可以使用根据 lombok 网站的@Data

@Data All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, @Setter on all non-final fields, and @RequiredArgsConstructor! @Data 现在全部在一起:@ToString、@EqualsAndHashCode、所有字段上的@Getter、所有非最终字段上的@Setter 和@RequiredArgsConstructor 的快捷方式!

@Data
public class BigGeneratedPojo {
  public String firstField;
  public int secondField;
  ...
  public ComplexObject nthField;
}

You can try to generate the proxy beans dynamically, for instance, using BitBuddy: https://bytebuddy.net/您可以尝试动态生成代理 bean,例如,使用 BitBuddy: https://bytebuddy.net/

The sample below shows how to proxy a property field of a method.下面的示例显示了如何代理方法的属性字段。 Note that this is only a sample, and most probably you might have to wrap it and add some dynamic using reflections, but I think it's quite an interesting option if you wish to dynamically extend code.请注意,这只是一个示例,很可能您可能必须包装它并使用反射添加一些动态,但我认为如果您希望动态扩展代码,这是一个非常有趣的选择。

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);
    }



}

Given your constraints, I'd add another code generation step.鉴于您的限制,我将添加另一个代码生成步骤。 How to implement it exactly depends on your build system (Maven/Gradle/something else), but JavaParser or Roaster will allow you to parse BigGeneratedPojo.java and create a subclass with the desired getters/setters, and the build system should automatically update it if BigGeneratedPojo changes.如何实现它完全取决于您的构建系统(Maven/Gradle/其他),但JavaParserRoaster将允许您解析BigGeneratedPojo.java并使用所需的 getter/setter 创建一个子类,并且构建系统应该自动更新它如果BigGeneratedPojo发生变化。

IDEs like Eclipse and STS provide option to add getters/setters methods. Eclipse 和 STS 等 IDE 提供了添加 getter/setter 方法的选项。 we can use those option to create setters/getters methods我们可以使用这些选项来创建 setter/getters 方法

I would suggest using reflection to get the public fields from your class and create the getters and setters using your own Java program as follows.我建议使用反射从您的 class 获取公共字段,并使用您自己的 Java 程序创建 getter 和 setter,如下所示。 Consider the following class as an example.以下面的 class 为例。

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());
    }
}

The code is taken from here - slightly modified to avoid unnecessary System.out .代码取自此处-稍作修改以避免不必要的System.out You can easily create a file from your main function and put your getters and setters there.您可以轻松地从您的main function 创建一个文件,并将您的 getter 和 setter 放在那里。

You can check the program by running it here as well.您也可以通过在此处运行程序来检查程序。 I hope that helps.我希望这会有所帮助。

You can use Lombok.您可以使用龙目岛。 Is is easy to use and implement.易于使用和实施。 It will create getters and setter in.class file post compilation.它将在编译后的 class 文件中创建 getter 和 setter。 It also keeps the code look cleaner.它还使代码看起来更干净。

@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;
}

} }

You are basically looking for Lombok .您基本上是在寻找Lombok It will generate getters and setters at compile time and you don't need to write any of them in your code.它将在编译时生成 getter 和 setter,您无需在代码中编写它们中的任何一个。

Or you can use reflection to get the fields and then pass their values around but that's a very bad idea.或者您可以使用反射来获取字段,然后传递它们的值,但这是一个非常糟糕的主意。

暂无
暂无

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

相关问题 杰克逊反序列化:如何将特定属性映射到getter和setter以及将所有属性加载到同一个POJO的映射中? - Jackson Deserialization: How to map specific properties to getters and setters as well as loading all the properties into map of a same POJO? 有效地使用大量的吸气剂和吸气剂填充POJO - Efficiently populating a POJO with a large amount of getters and setters java.util.properties的获取器/设置器 - Getters/Setters for java.util.properties Hibernate如何将设置器/获取器映射到属性? - How does Hibernate map setters/getters to properties? Java Reflection-列出类的属性(获取器和设置器) - Java Reflection - listing properties (getters & setters) of a class 使用批注(带有AOP?)将字段(带有getter和setter)注入POJO - Using annotations (with AOP?) to inject fields (with getters and setters) into POJO 在 JavaDoc 中记录 setter/getter、属性和构造函数时,有没有办法避免文档重复? - Is there a way to avoid documentation duplication when documenting setters/getters, properties and constructors in JavaDoc? 有没有办法在 Eclipse 中自动生成 getter 和 setter? - Is there a way to automatically generate getters and setters in Eclipse? 通过getter和setter更新pojos的通用方法 - Generic way to update pojos via getters and setters eclipse中是否有一种方法可以使用getter和setter生成简单的类 - Is there a way in eclipse to to generate a simple class with getters and setters
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM