使用 Reflection 你可以。调用 static newBuilder 方法来创建构建器。
查找所有 fieldssetters 对于特定 POJO 类。如果在所有情况下 setters 关于建筑商和 setters 关于 POJO 有相同的名称,就像你的例子一样,应该很容易转换。
调用 build 在建造者实例上创建新的 POJO.
使用基本 Java Reflection 和 Stream API-s,它可以像下面的样子。import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Properties;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.stream.Stream;
public class ReflectionApp {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("name", "John");
properties.put("date", "today");
AvroPropertie manualInstance = AvroPropertie.newBuilder()
.setName(properties.getProperty("name"))
.setDate(properties.getProperty("date"))
.build();
Object dynamicInstance = AvroAutoCoder.createAndSet(AvroPropertie.class, properties::getProperty);
System.out.println(manualInstance);
System.out.println(dynamicInstance);
System.out.println("manualInstance == dynamicInstance => " + manualInstance.equals(dynamicInstance));
}
}
class AvroAutoCoder {
public static Object createAndSet(Class clazz, Function dataSupplier) throws Exception {
Object builderInstance = findMethod(clazz, "newBuilder")
.invoke(null);
Class> builderClass = builderInstance.getClass();
getSetters(clazz).forEach(setter -> {
try {
String fieldName = setter.getName().substring(3).toLowerCase();
findMethod(builderClass, setter.getName())
.invoke(builderInstance, dataSupplier.apply(fieldName));
} catch (Exception e) {
throw new IllegalStateException(e);
}
});
return findMethod(builderClass, "build")
.invoke(builderInstance);
}
private static Method findMethod(Class clazz, String methodName) {
return Arrays.stream(clazz.getDeclaredMethods())
.filter(method -> method.getName().equals(methodName))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
private static Stream getSetters(Class clazz) {
return Arrays.stream(clazz.getDeclaredMethods())
.filter(method -> method.getParameterCount() == 1 && method.getReturnType() == Void.TYPE)
.filter(method -> method.getName().startsWith("set"));
}
}
上面的代码可以打印出来AvroPropertie[name='John', date='today']
AvroPropertie[name='John', date='today']
manualInstance == dynamicInstance => true
问题作者添加的注释。
在这个特定的例子中 APropertie 有一个静态的内部类,名为 Builder 其中持有想要的设置器。在这种情况下 getSetters() 方法需要稍微改变一下。// Find all setter of class
private static Stream getSetters2(Class clazz) {
Optional first = Arrays.stream(clazz.getDeclaredClasses())
.findFirst();
return Arrays.stream(first.get().getDeclaredMethods())
.filter(method -> method.getName().startsWith("set"));
}