原文地址:[https://jaxb.java.net/tutorial/section_6_2_5-Controlling-Element-Selection-XmlAccessorType-XmlTransient.html#Controlling Element Selection: XmlAccessorType, XmlTransient](https://jaxb.java.net/tutorial/section_6_2_5-Controlling-Element-Selection-XmlAccessorType-XmlTransient.html#Controlling Element Selection: XmlAccessorType, XmlTransient)
如果JAXB将一个类绑定到了XML,那么默认地,所有的public成员将会被绑定。比如,公共的getter和setter方法对,或者公共的field。任何protected,package-visible或者private的成员都会被绑定,如果它被添加了一个合适的注解,比如@XmlElement
或者@XmlAttribute
。你有若干的可能性来影响它的默认行为。
你可以将一个package或者一个顶层的class用@XmlAccessorType
来注解,然后设置它的value元素的值为枚举常量中的其中一个(FIELD
, PROPERTY
, PUBLIC_MEMBER
, NONE
)。如果FIELD
被设置,那么每一个非static和非transient的field将会被自动地绑定。设置为PROPERTY
可以告诉JAXB去为getter和setter方法对做数据绑定。NONE
的设置会禁止绑定,除了对那些已经被明确注解的field或property。一个没有使用这个注解的类将会从它的父类或者package设置中继承。
另一个在这个上下文中被提及的注解是@XmlTransient
。它会为它的target阻止绑定操作,这个target可以是一个class或者一个field或者一个method。如果你遇到了从public field导致的名字冲突(拿foo来说,getFoo和setFoo),那么使用@XmlTransient
将会是很有用的。
第一个class将访问类型设置为PUBLIC_MEMBER
来限制一组XML元素。成员getB
在绑定的时候将会被锁定。
@XmlAccessorType( XmlAccessType.PUBLIC_MEMBER )
public class SomeClass {
private String a;
private String b;
public SomeClass(){ ... }
public String getA(){ ... }
public void setA( String value ){ ... }
@XmlTransient
public String getB(){ ... }
public void setB( String value ){ ... }
}
与其对应的XML schema类型定义将会像下面这样:
<xs:complexType name="someClass">
<xs:sequence>
<xs:element name="a" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
第二个例子展示了反向的过程。它展示了一个被设置为最高限制访问类型的class,这个class有一个成员被明确注解成为一个element。
@XmlAccessorType( XmlAccessType.NONE )
public class OtherClass {
private String a;
private String b;
public OtherClass(){ ... }
public String getA(){ ... }
public void setA( String value ){ ... }
@XmlElement( required = true )
public String getB(){ ... }
public void setB( String value ){ ... }
}
由于我们已经将element的注解设置为true,那么生成的schema片段就将会有一点点不同:
<xs:complexType name="otherClass">
<xs:sequence>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
</xs:complexType>
最后这个例子展示了使用这些注解在一些特殊的情况下。首先,@XmlTransient
被用在public field上来避免方法对的名字冲突。其次,@XmlElement
被用来为getB请求绑定,而它并没有自己的setB配偶。(getter方法遵循JAXB为elements绑定到List<?>所生成Java代码的标准模式,在list对象上有一些改变)
@XmlAccessorType( XmlAccessType.PUBLIC_MEMBER )
public class SpecialClass {
@XmlTransient
public String a;
private List<String> b;
public SpecialClass(){ ... }
public String getA(){ ... }
public void setA( String value ){ ... }
@XmlElement
public List<String> getB(){
if( b == null ) b = new ArrayList<String>();
return b;
}
}
生成的复合类型会将两个element都包含在内。
<xs:complexType name="specialClass">
<xs:sequence>
<xs:element name="a" type="xs:string" minOccurs="0"/>
<xs:element name="b" type="xs:string" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
总的来看,你可以通过在package级别设置,给在一个包中的所有class指定策略;或者通过在class级别设置,给它所有的子类指定策略。这个策略可以在field或者property上,并且是很宽松的。也可以是很严格地默认什么也不允许。在这个class中,你可以通过添加@XmlElement
或者@XmlAttribute
来扩展一个限制严格的设置。或者你可以使用@XmlTransient
注解来禁止绑定。