对于JAXB注释类,是否有类似PostConstruct的东西?

时间:2009-10-09 18:53:22

标签: java dependency-injection constructor jaxb instantiation

我需要在一个类被解组后对它执行某些操作 (在由JAXB构建之后,而不是由我自己构建)。

JAXB中是否有这样的功能?

如果没有,我怎么能实现它?

3 个答案:

答案 0 :(得分:5)

您可以使用'class defined'事件回调。 在这里阅读更多http://java.sun.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.html#unmarshalEventCallback
例如,将此方法放在JAXB对象中:

    //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 );
    }

答案 1 :(得分:3)

尽管JAXB中似乎没有要求的功能,但我还是成功了 实现朝着正确方向发展的事情:

  • 我正在使用JSR-305的@PostConstruct注释 (它只是一个缺乏注释,JSR没有提供任何功能)
  • 我向unmarshaller添加了一个unmasrshaller-listener,每次对象被解组时都会被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 - 注释方法的检查,以确保它是最终的 你认为这是一个有用的限制吗?

用法

以下是该概念的使用方法。

@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

答案 2 :(得分:0)

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

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