JAXB 中是否有这样的功能可以在解组后(即在由 JAXB 构造后)对类执行操作?如果没有,我怎么能做到这一点?
问问题
2083 次
3 回答
6
您可以使用在您的 JAXB 类中定义的JAXB Unmarshal 事件回调,例如:
// This method is called after all the properties (except IDREF) are unmarshalled for this object,
// but before this object is set to the parent object.
void afterUnmarshal( Unmarshaller u, Object parent )
{
System.out.println( "After unmarshal: " + this.state );
}
于 2010-07-07T06:23:24.737 回答
3
尽管 JAXB 中似乎不存在所需的功能,但我设法实现了朝着正确方向发展的目标:
- 我正在使用 JSR-305 的
@PostConstruct
注释
(它只是一个 nacked 注释,JSR 不提供任何功能) - 我向解组器添加了一个解组器侦听器,每次解组对象时都会由 JAXB 调用它。
- 我使用 Java 反射检查此对象并搜索
@PostConstruct
方法上的注释 - 我执行方法
经测试。作品。
这是代码。抱歉,我正在使用一些外部反射 API 来获取所有方法,但我认为这个想法是可以理解的:
执行
JAXBContext context = // create the context with desired classes
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setListener(new Unmarshaller.Listener() {
@Override
public void afterUnmarshal(Object object, Object arg1) {
System.out.println("unmarshalling finished on: " + object);
Class<?> type = object.getClass();
Method postConstructMethod = null;
for (Method m : ReflectionUtils.getAllMethods(type)) {
if (m.getAnnotation(PostConstruct.class) != null) {
if (postConstructMethod != null) {
throw new IllegalStateException(
"@PostConstruct used multiple times");
}
postConstructMethod = m;
}
}
if (postConstructMethod != null) {
System.out.println("invoking post construct: "
+ postConstructMethod.getName() + "()");
if (!Modifier.isFinal(postConstructMethod.getModifiers())) {
throw new IllegalArgumentException("post construct method ["
+ postConstructMethod.getName() + "] must be final");
}
try {
postConstructMethod.setAccessible(true); // thanks to skaffman
postConstructMethod.invoke(object);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
}
});
编辑
添加了一个检查@PostConstruct
-annotated 方法,以确保它是最终的。
你认为这是一个有用的限制吗?
用法
以下是如何使用这个概念。
@XmlAccessorType(XmlAccessType.NONE)
public abstract class AbstractKeywordWithProps
extends KeywordCommand {
@XmlAnyElement
protected final List<Element> allElements = new LinkedList<Element>();
public AbstractKeywordWithProps() {
}
@PostConstruct
public final void postConstruct() {
// now, that "allElements" were successfully initialized,
// do something very important with them ;)
}
}
// further classes can be derived from this one. postConstruct still works!
提交了功能请求
于 2009-10-09T20:23:29.237 回答
0
这不是 100% 的解决方案,但您始终可以为这种类型注册XmlAdapter
使用@XmlJavaTypeAdapter annotation
。
缺点是您必须自己序列化该类(?)。我不知道访问和调用默认序列化机制的任何简单方法。但是使用自定义 [ XmlAdapter
] 您可以控制类型如何序列化以及在它之前/之后会发生什么。
于 2009-10-09T19:57:25.560 回答