3

JAXB 中是否有这样的功能可以在解组后(即在由 JAXB 构造后)对类执行操作?如果没有,我怎么能做到这一点?

4

3 回答 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!

提交了功能请求

https://jaxb.dev.java.net/issues/show_bug.cgi?id=698

于 2009-10-09T20:23:29.237 回答
0

这不是 100% 的解决方案,但您始终可以为这种类型注册XmlAdapter使用@XmlJavaTypeAdapter annotation

缺点是您必须自己序列化该类(?)。我不知道访问和调用默认序列化机制的任何简单方法。但是使用自定义 [ XmlAdapter] 您可以控制类型如何序列化以及在它之前/之后会发生什么。

于 2009-10-09T19:57:25.560 回答