【问题标题】:How to use JAXB annotations at runtime如何在运行时使用 JAXB 注释
【发布时间】:2011-10-31 17:20:09
【问题描述】:

我有以下 bean 类

@XmlRootElement(name = "book")
//Optional
@XmlType(propOrder = {"name" })
public class Book {

private String name;
private int num;

@XmlTransient
public int getNum() {
    return num;
}

public void setNum(int num) {
    this.num = num;
}

// name for your XML-Output:
@XmlElement(name = "bookName")
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
}

以及对应的编组码

private static void marshalXML(Book bookstore) {

    Writer w = null;
    try {
        // create JAXB context and instantiate marshaller
        JAXBContext context = getContext();
        if (context != null) {
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(bookstore, System.out);
            w = new FileWriter(BOOKSTORE_XML);
            m.marshal(bookstore, w);
        }
    } catch (Exception e) {
        System.out.println("error in marshalling");
    } finally {
        try {
            w.close();
        } catch (Exception e) {
        }
    }
}

我想让属性在运行时可配置,我想在运行时在“num”上指定@xmltransient 而不是编译时。我该怎么做?

【问题讨论】:

  • 最好的解决方案是拥有两个模型类 (Y extends X):X 具有“正常”注释,Y 在 num 上具有 @XmlTransient
  • 我希望通过一些 xml 或其他方式完成此配置
  • 究竟是什么配置?从 XML 的角度来看(我在之前的评论中忽略了这一点),您可以在不同的命名空间中建模两个 XML 标记(<ns1:book><num/></ns1:book> = X 和 <ns2:book></ns2:book> = Y)。
  • 我的代码在编译时将 attr "num" 指定为 @xmltransient,我希望他在运行时完成

标签: java jaxb


【解决方案1】:

注意:我是 EclipseLink JAXB (MOXy) 负责人,也是 JAXB 2 (JSR-222) 专家组的成员。

MOXy JAXB 实现提供了通过其MetadataSource 扩展在运行时操作映射元数据的能力。详细示例见:

【讨论】:

  • 感谢项目链接!我试过M2 repo,但结果是404——也许你可以解决这个问题。我还认为this page 上的示例应为address.set("street", "123 A Street"); address.set("city", "Any Town");
【解决方案2】:

可以在运行时注入注解。

我们公司的一个人在课堂上尝试过这个,看那个代码:

https://github.com/OlivierCroisier/AnnotationInjector/blob/master/src/main/java/net/thecodersbreakfast/annotationinjector/AnnotationInjector.java

请注意,它只在类上注入注释。他说用方法或构造函数做同样的事情更难。我不确定他在法语幻灯片中所说的一切(最后是http://www.slideshare.net/Zenika/annotations-paris-jug) 但似乎你想要的可能是可能的,但你的注释只会出现在你修改它们的实例上,而不是所有实例上(但这也许是你想要的?)

但是他没有告诉如何在字段或特定实例的方法上获取注释映射,我不知道如何获取它。 请注意,许多 JDK 方法返回复制的值,因此您不能只修改 getAnnotations() 的数组,它不会有任何效果......(但似乎有必要初始化类上的 annotations 字段,参见他的代码)

祝你好运,或许可以尝试联系他。

编辑:您可以简单地创建 2 个不同的类并选择正确的类在运行时使用?如果您不能使用 MOXy,这对我来说似乎更容易。 但是我认为您将无法覆盖带有/不带有 xmltransient 的方法,因为它们似乎在该 JAXB 注释上没有 @Inherited (但我可能是错的,从未测试过注释继承......

【讨论】:

  • 非常棘手的解决方案 :) Slide 54 拥有解决方案:Field mapRef = Class.class.getDeclaredField("annotations"); mapRef.setAccessible(true); Map<Class, Annotation> annots = (Map<Class, Annotation>) mapRef.get(targetClass); ... mapRef.set(targetClass, newAnnotations);
【解决方案3】:

您可能可以编写自定义适配器(请参阅 javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter 和 XmlAdapter)。但是你为什么要这样做呢?

【讨论】:

  • 我想让它可定制,可能是我正在制作瞬态的 attr 稍后将更改为非瞬态
  • 好吧,有一个解决方法:@XmlElement(name = "bookNum", required = false) public Integer getNum() { if (isNumTransient()) { return null; } else { return num; } }
猜你喜欢
  • 1970-01-01
  • 2014-05-17
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2016-08-31
相关资源
最近更新 更多