【发布时间】:2009-10-09 18:53:21
【问题描述】:
在 JAXB 中是否有这样的功能可以在解组后(即在由 JAXB 构造后)对类执行操作?如果没有,我怎么能做到这一点?
【问题讨论】:
-
很好的问题,但我不认为有这样的事情。不过,可能而且应该有,我鼓励您在 jaxb.dev.java.net 上记录功能请求
标签: java dependency-injection constructor jaxb instantiation
在 JAXB 中是否有这样的功能可以在解组后(即在由 JAXB 构造后)对类执行操作?如果没有,我怎么能做到这一点?
【问题讨论】:
标签: java dependency-injection constructor jaxb instantiation
您可以使用在您的 JAXB 类中定义的 JAXB Unmarshal Event Callbacks,例如:
// 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 );
}
【讨论】:
虽然 JAXB 中似乎不存在所需的功能,但我设法做到了 实现朝着正确方向发展的目标:
@PostConstruct 注释@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!
【讨论】:
postConstructMethod 上调用setAccessible(true),这应该会强制它成为可调用的。
这不是 100% 的解决方案,但您始终可以使用 @XmlJavaTypeAdapter annotation 注册 XmlAdapter
对于这种类型。
缺点是您必须自己序列化该类(?)。我不知道访问和调用默认序列化机制的任何简单方法。但是使用自定义 [XmlAdapter],您可以控制类型如何序列化以及在它之前/之后发生什么。
【讨论】: