使用生成的 Java 源代码,例如
- 使用 Hibernate 工具生成的代码
- 使用 JAXB 模式绑定 (xjc) 生成的代码
- 使用 WDSL2Java (cxf) 生成的代码
所有生成的类都是“值对象”类型,没有业务逻辑。如果我在生成的源代码中添加方法,如果我重复源代码生成,我将失去这些方法。
这些 Java 代码生成工具是否提供了“扩展”生成代码的方法?
例如,
- 覆盖 ToString 方法(用于记录)
- 实现访问者模式(用于数据分析/验证)
使用生成的 Java 源代码,例如
所有生成的类都是“值对象”类型,没有业务逻辑。如果我在生成的源代码中添加方法,如果我重复源代码生成,我将失去这些方法。
这些 Java 代码生成工具是否提供了“扩展”生成代码的方法?
例如,
对于 JAXB,请参阅添加行为。
基本上,您将 JAXB 配置为返回您通常期望的对象的自定义实例。在下面的示例中,您将创建一个扩展 JAXB 对象 Person 的新对象 PersonEx。这种机制运行良好,因为您是从生成的类派生的,根本不改变 JAXB 类或模式。
package org.acme.foo.impl;
class PersonEx extends Person {
@Override
public void setName(String name) {
if(name.length()<3) throw new IllegalArgumentException();
super.setName(name);
}
}
@XmlRegistry
class ObjectFactoryEx extends ObjectFactory {
@Override
Person createPerson() {
return new PersonEx();
}
}
请注意,如果您的 JAXB 对象发生更改,@Override 指令很重要——它将防止您的自定义成为孤立的。
至于 Hibernate,您可以调整代码生成中使用的模板文件来改变它们的行为。如果你想调整你可以编辑的 HIbernate 工具,例如:dao/daohome.ftl
您甚至可以在编辑.hbm.xml文件的“toString()”输出中添加字段
...
<property name="note" type="string">
<meta attribute="use-in-tostring">true</meta>
<column name="note" />
</property>
...
对于日志记录和验证,您可以考虑将AOP 与 AspectJ 一起使用(我不建议弄乱生成的代码,因为您可能希望多次从头开始构建它)。
首先,我要重申,修改生成的代码有很多与之相关的问题,应该尽可能避免。也就是说,有时避免或比仅在重新生成代码时处理更改更努力是不切实际的。
遗憾的是,java 不支持 c# 具有的部分类的概念。这些正是为了解决这类问题。
您应该查看您的代码生成工具是否支持某种形式的有意义的注释,这些注释分隔您在类中添加的区域(如果您正在修改代码而不是添加代码,这不太可能并且无济于事)
如果您真的希望这样做,最好的选择是最初生成文件,但立即将它们检入版本控制存储库。然后进行更改,检查。
下次您重新运行工具并让它们覆盖现有文件时,您可以与源代码控制的文件进行比较并将更改合并回来(大多数琐碎的更改,例如添加新列/表将不费吹灰之力。
如果代码生成器突然生成完全不同的代码(比如新版本),这对您没有太大帮助,但在这种情况下,您添加的任何代码,不仅仅是依赖于已经公开公开的数据/方法的附加便利方法)都会有问题不管它是如何混入课堂的。但是,版本控制系统仍然有帮助,因为它还记录了原始更改,因此您可以查看之前添加的内容,以及假设您需要以新样式重新创建的内容。
编辑生成的代码文件不是一个好主意,无论是通过编辑文件本身还是通过子类化。无论您做什么,请务必保持该工具创建的签名完好无损,以便将来可以了解该文件是自动生成的。
我建议您研究工具的命令选项,看看它们是否允许您有一定的灵活性。一些工具可以生成抽象类或接口而不是具体类。如果这不可能,请创建一个域对象,其中包含自动生成的对象作为成员变量。
我使用 Hibernate 的方式是生成然后扩展的基类。我将我所有的业务逻辑(如果有的话)添加到这些子类中。我还经常最终更改 Hibernate 使用的 FreeMarker 模板以进一步自定义生成的类。
AOP 引用是一个很好的引用。我将添加 Spring,它内置了非常好的 AOP 功能。