Какую информацию о пакете я комментирую с помощью XmlJavaTypeAdapters?
Я изучил Блейз Дохан, отвечая на вопрос по этому вопросу, но у вас есть еще один вопрос.
XmlJavaTypeAdapters
позволяет вам перечислить кучу аннотаций XmlJavaTypeAdapter
, каждый из которых определяет, как не привязываемый тип сопоставляется с привязываемым типом по JAXB.
Вы можете использовать эту аннотацию на уровне пакета. Когда вы это делаете, каждая аннотация XmlJavaTypeAdapter
нуждается в полном атрибуте type()
.
Как представляется, не требуется требование, чтобы пакет, который был аннотирован, имеет какое-либо отношение к пакету адаптируемых типов, не подлежащих связыванию. Это удобно и приятно.
Это, однако, приводит меня к следующему вопросу: если нет никакой связи между аннотированным пакетом и пакетом адаптируемого типа, как JAXB обнаруживает аннотации на уровне пакетов XmlJavaTypeAdapters
? Как, другими словами, он знает, какие пакеты проконсультироваться для потенциальных аннотаций XmlJavaTypeAdapters
? Могу ли я сделать случайный пакет, скажем, в файле .jar
в каталоге .ear
file lib
, который содержит один, ginormous package-info
класс, который аннотируется со всеми адаптерами для всех моих не связанных между собой типов
Ответы
Ответ 1
Когда среда выполнения JAXB загружает класс, аннотированный JAXB, он ищет package-info.java
в том же пакете, что и этот класс, и проверяет, что искать аннотации на уровне пакета. Поэтому, пока XmlJavaTypeAdapters
не должен находиться в том же пакете, что и типы "не привязываемые", он должен находиться в том же пакете, что и типы "bindable".
Например, скажем, у меня есть JAXB-аннотированный класс A
, в пакете X
, который имеет свойство типа B
в пакете Y
. Чтобы связать свойство B
, скажем, требуется адаптер типа. Этот адаптер можно указать непосредственно в A
или он может быть указан в package-info.java
в пакете X
. Пакет Y
в значительной степени произволен и не представляет интереса для среды выполнения JAXB.
Надеюсь, это имеет смысл.
Ответ 2
Там, как представляется, не требуется, чтобы пакет, который будучи аннотированными, имеют какое-либо отношение к пакету не привязываемые типы. Это удобно и приятно.
Это правильно. Когда @XmlJavaTypeAdapter
используется на уровне пакета, это означает, что этот адаптер применяется ко всем свойствам указанного типа для классов, которые находятся в этом пакете. Ниже я приведу пример.
forum8735737.bar.package-инфо
В этом пакете мы укажем XmlAdapter
, который будет применяться ко всем полям/свойствам типа String
внутри этого пакета.
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum8735737.bar;
import javax.xml.bind.annotation.adapters.*;
forum8735737.bar.StringAdapter
Наш XmlAdapter
будет просто преобразовывать все экземпляры String
в верхний регистр при сортировке:
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();
}
}
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;
}
}
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;
}
}
Demo
В следующем коде создаются экземпляры как 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);
}
}
Выход
Обратите внимание, что значение элемента 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>