如何扩展JAXB、CXF或Hibernate工具生成的Java代码?

如何扩展JAXB、CXF或Hibernate工具生成的Java代码?,java,hibernate,code-generation,jaxb,cxf,Java,Hibernate,Code Generation,Jaxb,Cxf,使用生成的Java源代码,如 使用Hibernate工具生成的代码 使用JAXB模式绑定(xjc)生成的代码 使用WDSL2Java(cxf)生成的代码 所有生成的类都是“值对象”类型,没有业务逻辑。如果我向生成的源代码中添加方法,如果我重复生成源代码,我将丢失这些方法 这些Java代码生成工具是否提供了“扩展”生成代码的方法 比如说, 重写ToString方法(用于日志记录) 实现访问者模式(用于数据分析/验证) 编辑生成的代码文件不是一个好主意,无论是通过编辑文件本身还是通过子类化。无

使用生成的Java源代码,如

  • 使用Hibernate工具生成的代码
  • 使用JAXB模式绑定(xjc)生成的代码
  • 使用WDSL2Java(cxf)生成的代码
所有生成的类都是“值对象”类型,没有业务逻辑。如果我向生成的源代码中添加方法,如果我重复生成源代码,我将丢失这些方法

这些Java代码生成工具是否提供了“扩展”生成代码的方法

比如说,

  • 重写ToString方法(用于日志记录)
  • 实现访问者模式(用于数据分析/验证)

编辑生成的代码文件不是一个好主意,无论是通过编辑文件本身还是通过子类化。无论您做什么,都要确保该工具创建的签名完好无损,以便将来能够理解该文件是自动生成的


我建议您研究一下这些工具的命令选项,看看它们是否给您带来了一些灵活性。有些工具可以生成抽象类或接口,而不是具体类。如果不可能,请创建包含自动生成对象作为成员变量的域对象

对于Hibernate,您可以调整代码生成中使用的模板文件以更改其行为。如果您想调整HIbernate工具,您可以编辑,例如:dao/daohome.ftl

您甚至可以在编辑.hbm.xml文件时向“toString()”输出中添加字段

...
<property name="note" type="string">
    <meta attribute="use-in-tostring">true</meta>
    <column name="note" />
</property>
...
。。。
真的
...

<> P>日志记录和验证都可以考虑使用(我不建议弄乱生成的代码,因为您可能希望从头开始多次构建)。

首先我会重申,生成代码的修改有许多与之相关的问题,并且在可能的情况下应该避免。这就是说,有时避免这种情况是不切实际的,或者比重新生成代码时只处理更改更费劲

遗憾的是,java不支持c#所拥有的部分类的概念。正是为了解决这类问题

您应该看看您的代码生成工具是否支持某种形式的有意义的注释,这些注释对您自己在类中添加的区域进行了分隔(如果您修改代码而不是添加到代码中,这是不可能的,也不会有帮助的)

如果确实希望这样做,最好的选择是最初生成文件,但立即将其签入版本控制存储库。 然后进行更改,并将其签入

下次重新运行这些工具并让它们覆盖现有文件时,您可以将其与源代码控制的文件进行区分,并将更改合并回来(最简单的更改,如添加新的列/表,将不费吹灰之力)

如果代码生成器突然生成完全不同的代码(比如一个新版本),这对您没有多大帮助,但是在这种情况下,您添加的任何代码(不仅仅是依赖于已经公开的数据/方法的附加方便方法)都会有问题,无论它如何混合到类中。但是,版本控制系统仍然有帮助,因为它还记录了原始更改,因此您可以看到以前添加的内容,以及您需要以新样式重新创建的内容。

对于JAXB,请参阅

基本上,您可以将JAXB配置为返回您通常期望的对象的自定义实例。在下面的示例中,您创建了一个新的object PersonEx,它扩展了JAXB object Person。这种机制工作得很好,因为您是从生成的类派生的,并且根本不改变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();
  }
}
package org.acme.foo.impl;
类PersonEx扩展人{
@凌驾
公共void集合名(字符串名){

如果(name.length()AOP引用是一个很好的引用。我将添加Spring,它内置了非常好的AOP功能。

我使用Hibernate的方式是生成基类,然后进行扩展。我添加了所有业务逻辑(如果有的话)我还经常更改Hibernate使用的FreeMarker模板,以进一步自定义生成的类。

看看


这是我为JAXB编写的一个小插件,使用起来非常简单。希望它能有所帮助

这看起来很棒,我在几天前发现了JAXB和CXF,它们看起来都非常强大,而且可配置性很好。我过去使用过它,在多个团队中,您可以使用相同的模式并实现不同的行为(这是不是一件好事值得商榷!)除了上面提到的(这是一个很好的建议),jaxb代码生成器(xjc)确实有一个插件机制,允许代码生成器生成额外的“东西”插件、hashCode插件等等…添加这些东西。你也可以自己编写。上面的东西对于业务逻辑的东西肯定更好,但是对于你想要应用到所有类的简单东西,插件都可以工作。这实际上是一个相当好的方法。Hibernate可以实例化子类,并且生成的类永远不会被使用直接。很容易重新生成超类,如果模型中有影响业务方法的更改,则子类中的编译错误很容易修复。这很方便,但从设计的角度来看不是很清楚。您的子类在数据访问和业务层都起作用-这不利于conc的分离erns原则。子类化的缺点是什么?例如,它似乎是Hibernate生成的类的有效解决方案。唯一的缺点是,如果重新生成Hibernate类,您的类可能会中断。我想这没什么大不了的,但是我个人更喜欢组合和使用Hibernate类的实例mber变量。最重要的是弄清楚哪些类是au