在我的一个项目中,我有两个包含DTO的包,POJO只有吸气剂和固定剂。虽然重要的是它们是简单的Java bean(例如,因为Apache CXF使用它们来创建Web服务XSD等),但它也很糟糕且容易出错。
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
我更喜欢流畅的界面和构建器对象,因此我使用maven / gmaven自动为DTO创建构建器。因此,对于上面的代码,会自动生成FooBuilder
,我可以这样使用:
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
我还自动为生成的Builders生成单元测试。单元测试将生成上述两个代码(构建器版本和非构建器版本),并断言两个版本在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);
}
}
另一个非常重要的方面是pojos有时会有收集成员。 e.g:
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;
构建器构建器(sic)读取注释并将该值用作要生成的方法的泛型类型。
我们现在越来越接近这个问题了(对不起,简洁不是我的优点之一: - ))。
我已经意识到这个构建器方法可以在多个项目中使用,所以我想把它变成一个maven插件。我非常清楚如何生成maven插件,因此这不是问题的一部分(也不是如何生成有效的Java源代码)。我的问题是:如何在不引入任何公共依赖项的情况下处理上述两个问题(在Project和Plugin之间):
<Question>
我需要一个Defaults类(或类似的机制)来获取生成的单元测试的默认值(这是概念的关键部分,如果没有经过全面测试,我不相信自动生成的构建器) 。鉴于每个项目都有自己的域对象,请帮我提出一个解决这个问题的好方法。
我需要一种将通用类型传递给构建器生成器的常用方法。我使用的当前基于注释的版本并不令人满意,因为项目和插件都需要知道相同的注释。
</Question>
任何想法?
BTW:我知道使用构建器的真正关键点是使对象不可变。我不能让我的不可变,因为标准的java bean是必需的,但我使用AspectJ强制在我的代码库中除了构建器之外的任何地方都没有调用set-methods和构造函数,所以出于实际目的,结果对象是不可变的另外:是的,我知道现有的Builder-generator IDE插件。这不符合我的目的,我想要一个自动化解决方案,每当底层代码发生变化时,它始终是最新的。
马特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
方法实例化对象并在其属性映射中分配所有属性。
答案 0 :(得分:2)
POJO是一个不遵循Java Bean spoec的对象。即。它没有setter / getters。
JavaBeans不需要有setter,如果你不想让它们被调用,就不要生成它们。 (您的构建器可以调用包本地或私有构造函数来创建不可变对象)
答案 1 :(得分:1)
你看过Diezel了吗? 它是一个Builder生成器。