我用XmlJavaTypeAdapters注释了什么package-info?

Lai*_*son 8 java jaxb

我已经研究过Blaise Doughan关于这个问题的答案,但还有一个问题.

XmlJavaTypeAdapters允许您列出一堆XmlJavaTypeAdapter注释,每个注释管理JAXB如何将不可绑定类型映射到可绑定类型.

您可以在包级别使用此批注.执行此操作时,每个XmlJavaTypeAdapter注释都需要type()完全指定其属性.

似乎没有要求正在注释的包与要调整的不可绑定类型的包有任何关系.这很方便,也很好.

然而,这引出了我的下一个问题:如果注释包与被调整类型的包之间没有关系,那么JAXB如何发现包级XmlJavaTypeAdapters注释?换句话说,它是如何知道哪些包可以咨询潜在的XmlJavaTypeAdapters注释?我可以.jar在我的.ear文件lib目录中创建一个随机包,其中包含一个单独的,巨大的package-info类,该类使用所有不可绑定类型的所有适配器进行注释?

ska*_*man 8

当JAXB运行时加载带有JAXB注释的类时,它会package-info.java在与该类相同的包中查找,并检查它以查找包级注释.因此,虽然XmlJavaTypeAdapters不必与"不可绑定"类型驻留在同一个包中,但必须与"可绑定"类型驻留在同一个包中.

例如,假设我有一个JAXB注释类A,在包X,其具有类型的属性B在包Y.为了绑定B属性,假设需要一个类型适配器.该适配器可以自己指定A,也可以package-info.java在包中指定X.包Y非常随意,对JAXB运行时没有兴趣.

我希望这是有道理的.


bdo*_*han 5

似乎没有要求正在注释的包与要调整的不可绑定类型的包有任何关系.这很方便,也很好.

这是对的.当@XmlJavaTypeAdapter在封装级使用它意味着这个适配器适用于为类驻留在这个包中的指定类型的所有属性.我将在下面举例说明.

forum8735737.bar.package-信息

对于此包,我们将指定一个XmlAdapter将应用于String此包中所有类型的字段/属性的包.

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum8735737.bar;

import javax.xml.bind.annotation.adapters.*; 
Run Code Online (Sandbox Code Playgroud)

forum8735737.bar.StringAdapter

我们XmlAdapterString在编组时简单地将所有实例转换为大写:

package forum8735737.bar;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class StringAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String v) throws Exception {
        return v;
    }

    @Override
    public String marshal(String v) throws Exception {
        if(null == v) {
            return v;
        }
        return v.toUpperCase();
    }

}
Run Code Online (Sandbox Code Playgroud)

forum8735737.bar.Bar

Bar表示此包中的POJO,其属性类型为String:

package forum8735737.bar;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Bar {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
Run Code Online (Sandbox Code Playgroud)

forum8735737.foo.Foo

Foo表示域对象,其属性类型String存在于不同的包中.该XmlAdapter所注册,我们forum8735737.bar包将不会适用于这个类:

package forum8735737.foo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
Run Code Online (Sandbox Code Playgroud)

演示

下面的代码将创建两个实例Foo,并Bar和他们编组为XML:

package forum8735737;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import forum8735737.bar.Bar;
import forum8735737.foo.Foo;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class, Bar.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        Foo foo = new Foo();
        foo.setName("Foo");
        marshaller.marshal(foo, System.out);

        Bar bar = new Bar();
        bar.setName("Bar");
        marshaller.marshal(bar, System.out);
    }

}
Run Code Online (Sandbox Code Playgroud)

产量

注意name内部元素的值是如何bar转换为大写的:

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <name>Foo</name>
</foo>
<?xml version="1.0" encoding="UTF-8"?>
<bar>
   <name>BAR</name>
</bar>
Run Code Online (Sandbox Code Playgroud)