Есть ли что-то вроде PostConstruct для JAXB-аннотированных классов? - PullRequest
2 голосов
/ 09 октября 2009

Мне нужно выполнить определенные операции над классом после его распаковки (после того, как он построен JAXB, а не мной).

Есть ли такая функциональность в JAXB?

Если нет, то как мне этого добиться?

Ответы [ 3 ]

5 голосов
/ 07 июля 2010

Вы можете использовать обратные вызовы событий, определенных классом. Подробнее здесь 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 );
    }
3 голосов
/ 10 октября 2009

Хотя требуемая функциональность отсутствует в JAXB, мне удалось достичь чего-то, что идет в правильном направлении:

  • Я использую аннотацию JSR-305 @PostConstruct
    (это просто прикрепленная аннотация, JSR не предоставляет никаких функций)
  • Я добавляю слушателя unmasrshaller к unmarshaller, который вызывается JAXB каждый раз, когда объект был unmarshalled.
  • Я проверяю этот объект с помощью отражения 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);
      }
    }
  }

});

EDIT
Добавлена ​​проверка для @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

0 голосов
/ 09 октября 2009

Это не 100% решение, но вы всегда можете зарегистрировать XmlAdapter, используя @XmlJavaTypeAdapter annotation для этого типа.

Недостатком было бы то, что вы должны сериализовать класс самостоятельно (?). Я не знаю ни о каком простом способе доступа и вызова механизма сериализации по умолчанию. Но с помощью custom [XmlAdapter] вы можете контролировать, как сериализуется тип и что происходит до / после него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...