在我的一个项目中,我有两个充满dto的包,pojo只有getter和setter。虽然它们是简单的JavaBean很重要(例如,因为ApacheCxf使用它们来创建Web服务XSD等),但是这样的程序也很糟糕,而且容易出错。
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
我更喜欢流畅的接口和构建器对象,所以我使用maven/gmaven自动为dto创建构建器。所以对于上面的代码,a
FooBuilder
是自动生成的,我可以这样使用:
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
我还为生成的构建器自动生成单元测试。单元测试将生成上述两个代码(构建器版本和非构建器版本),并断言这两个版本在
equals()
和
hashcode()
. 我可以实现这一点的方法是为每种属性类型创建一个具有默认值的全局可访问映射。像这样的:
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)
但在我的生成器中,我希望从这个例子中生成两个方法:set方法和add方法:
fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method
我已经解决了这个问题,在
Foo
@ComponentType(Bing.class)
private List<Bing> bings;
builder builder(sic)读取注释并使用该值作为要生成的方法的泛型类型。
我们现在离这个问题越来越近了(对不起,简短不是我的优点之一:-)。
我已经意识到这种构建方法可以在多个项目中使用,所以我正在考虑将其转换为maven插件。我非常清楚如何生成maven插件,所以这不是问题的一部分(也不是如何生成有效的Java源代码)。我的问题是:如何在不引入任何公共依赖项(在项目和插件之间)的情况下处理上述两个问题:
<Question>
-
我需要一个默认类(或类似的机制)来获取生成的单元测试的默认值(这是概念的关键部分,如果没有完全测试,我不会信任自动生成的构建器)。请帮助我想出一个好的通用方法来解决这个问题,因为每个项目都有自己的域对象。
-
我需要一种将泛型类型通信到生成器的通用方法。我目前使用的基于注释的版本并不令人满意,因为project和plugin都需要知道同一个注释。
</Question>
有什么想法吗?
顺便说一句:我知道使用构建器的真正关键是使对象不可变。我不能使我的对象不可变,因为标准的javabean是必要的,但是我使用AspectJ来强制在我的代码库中除了在构建器中之外的任何地方都不调用set方法或构造函数,因此出于实际目的,生成的对象是不可变的。
另外,是的,我知道现有的生成器生成器IDE插件。这不符合我的目的,我想要一个自动化的解决方案,只要底层代码改变,它总是最新的。
马特B要求一些关于我如何生成我的建设者的信息。我做的是:
我每次读一节课,用
Introspector.getBeanInfo(clazz).getPropertyDescriptors()
获取属性描述符数组。我所有的建设者都有一个基类
AbstractBuilder<T>
哪里
T
会是
福
在上述情况下。这是
the code of the Abstract Builder class
. 对于
PropertyDescriptor
数组,则生成具有属性名称的方法。这将是
FooBuilder.bar(String)
:
public FooBuilder bar(String bar){
setProperty("bar", bar);
return this;
}
这个
build()
方法
AbstractBuilder
实例化对象并分配其属性映射中的所有属性。