gpt4 book ai didi

Java Builder 生成器问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:55:08 24 4
gpt4 key购买 nike

在我的一个项目中,我有两个装满 DTO 的包,POJO 只有 getter 和 setter。虽然它们是简单的 java bean 很重要(例如,因为 Apache CXF 使用它们来创建 Web 服务 XSD 等),但像这样编程也很糟糕且容易出错。

Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;

我更喜欢流畅的接口(interface)和构建器对象,所以我使用 maven/gmaven 自动为 DTO 创建构建器。所以对于上面的代码,一个FooBuilder是自动生成的,我可以这样使用:

Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();

我还会为生成的构建器自动生成单元测试。单元测试将生成上述两种代码(构建器版本和非构建器版本)并断言这两个版本在 equals() 方面是等价的。和 hashcode() .我实现这一目标的方法是拥有一个全局可访问的 map ,其中包含每个属性类型的默认值。像这样:

public final class Defaults{
private Defaults(){}
private static final Map<Class<?>, Object> DEFAULT_VALUES =
new HashMap<Class<?>, Object>();
static{
DEFAULT_VALUES.put(String.class, "baz");
// argh, autoboxing is necessary :-)
DEFAULT_VALUES.put(int.class, 123);
// etc. etc.
}
public static getPropertyValue(Class<?> type){
return DEFAULT_VALUES.get(type);
}
}

另一个重要的方面是 pojo 有时有集合成员。例如:

foo.setBings(List<Bing> bings)

但在我的构建器中,我希望从这种情况下生成两个方法:一个设置方法和一个添加方法:

fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method

我通过向 Foo 中的属性字段添加自定义注释解决了这个问题

@ComponentType(Bing.class)
private List<Bing> bings;

构建器构建器 (sic) 读取注释并将该值用作要生成的方法的通用类型。

我们现在离这个问题越来越近了(抱歉,简洁不是我的优点之一:-))。

我意识到这种构建器方法可以用于多个项目,所以我正在考虑将它变成一个 maven 插件。我非常清楚如何生成 Maven 插件,所以这不是问题的一部分(也不是如何生成有效的 Java 源代码)。我的问题是:如何在不引入任何公共(public)依赖项(项目和插件之间)的情况下处理上述两个问题:

<Question>

  1. 我需要一个 Defaults 类(或类似的机制)来为生成的单元测试获取默认值(这是概念的关键部分,如果未经过全面测试,我不会信任自动生成的构建器) .请帮我想出一个好的通用方法来解决这个问题,因为每个项目都有自己的域对象。

  2. 我需要一种将泛型类型与构建器生成器通信的通用方法。我使用的当前基于注解的版本并不令人满意,因为项目和插件都需要知道相同的注解。

</Question>

有什么想法吗?

顺便说一句:我知道使用构建器的真正关键点是使对象不可变。我不能使我的不可变,因为标准的 java bean 是必需的,但我使用 AspectJ 强制在我的代码库中除了构建器之外的任何地方都不会调用设置方法和构造函数,因此出于实际目的,生成的对象是不可变的.

另外:是的,我知道现有的 Builder-generator IDE 插件。这不符合我的目的,我想要一个自动化的解决方案,只要底层代码发生变化,它就始终是最新的。


Matt B 要求提供一些有关我如何生成构建器的信息。这是我的做法:

我每次反射都读了一个类,使用 Introspector.getBeanInfo(clazz).getPropertyDescriptors()获取属性描述符数组。我所有的构建器都有一个基类 AbstractBuilder<T>其中 T将是 Foo在上述情况下。这是 the code of the Abstract Builder class .对于 PropertyDescriptor 中的每个属性数组,使用属性名称生成一个方法。这将是 FooBuilder.bar(String) 的实现:

public FooBuilder bar(String bar){
setProperty("bar", bar);
return this;
}

build() AbstractBuilder 中的方法实例化对象并在其属性映射中分配所有属性。

最佳答案

POJO 是不遵循 Java Bean spoec 的对象。 IE。它没有 setter/getter。

JavaBeans 不需要有 setter,如果你不想调用它们,就不要生成它们。 (您的构建器可以调用包本地或私有(private)构造函数来创建您的不可变对象(immutable对象))

关于Java Builder 生成器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4257028/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com