Хотя требуемая функциональность отсутствует в 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