3

クラスが非整列化された後、つまり JAXB によって構築された後に、そのクラスに対して操作を実行する JAXB の機能はありますか? そうでない場合、どうすればこれを達成できますか?

4

3 に答える 3

6

JAXB クラスで定義されている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 );
}
于 2010-07-07T06:23:24.737 に答える
3

要求された機能が JAXB に存在しないように見えますが、正しい方向に向かう何かを達成することができました。

  • 私は JSR-305 の@PostConstruct注釈を使用して
    います (これは単なる注釈であり、JSR によって提供される機能はありません)。
  • unmarshaller-listener を unmarshaller に追加します。これは、オブジェクトが非整列化されるたびに JAXB によって呼び出されます。
  • @PostConstructJava リフレクションを使用してこのオブジェクトを検査し、メソッドの注釈を検索します
  • メソッドを実行します

テスト済み。動作します。

これがコードです。申し訳ありませんが、すべてのメソッドを取得するためにいくつかの外部リフレクション 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);
      }
    }
  }

});

EDIT -annotated メソッド
のチェックを追加し、最終的なものであることを確認しました。 それは有用な制限だと思いますか?@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

于 2009-10-09T20:23:29.237 に答える
0

これは 100% の解決策ではありませんが、いつでも この型のXmlAdapterusingを登録できます。@XmlJavaTypeAdapter annotation

欠点は、クラスを自分でシリアル化する必要があることです (?)。デフォルトのシリアル化メカニズムにアクセスして呼び出す簡単な方法を知りません。ただし、カスタム [ XmlAdapter] を使用すると、型がどのようにシリアル化されるか、およびその前後に何が起こるかを制御できます。

于 2009-10-09T19:57:25.560 に答える