Я использую Javassist для добавления и изменения аннотаций на package-info
«класс».Почему Javassist настаивает на поиске значения аннотации по умолчанию, если он явно указан?
В некоторых случаях мне нужно иметь дело со следующим краевым корпусом. Кто-то (неправильно) указал аннотацию @XmlJavaTypeAdapters
на пакет package-info
, но не указал атрибут value
(который равен defined as being required). Так выглядит примерно так:
@XmlJavaTypeAdapters // XXX incorrect; value() is required, but javac has no problem
package com.foobar;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
В Javassist это немного странно.
javassist.bytecode.annotation.Annotation
, представляющий @XmlJavaTypeAdapters
аннотацию не имеет значения члена (getMemberValue("value")
возвращает null
), как и ожидалось.
Это, конечно, можно добавить value()
значение члена, и это то, что я сделал:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(new AnnotationMemberValue(constantPool), constantPool);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
В фрагменте кода выше, я создал новое значение члена для хранения массива аннотаций, поскольку атрибут value()
@XmlJavaTypeAdapters
представляет собой массив из @XmlJavaTypeAdapter
. Я указал свой тип массива, пытаясь угадать намерение Zen-подобной документации —, кажется, что если вы добавите еще один MemberValue
, то это MemberValue
будет каким-то образом служить типом массива. В моем случае я хочу, чтобы тип массива был @XmlJavaTypeAdapter
, что является аннотацией, поэтому единственным видом MemberValue
, который, как представляется, был AnnotationMemberValue
. Поэтому я создал пустую одну из них и задал ее как тип массива.
Это работает прекрасно, насколько это возможно, до тех пор, пока вы остаетесь «внутри» джавассиста.
Однако, похоже, что-то пошло не так. Если я попрошу Javassist преобразовать все свои проприетарные аннотации в подлинную Java java.lang.annotation.Annotation
, тогда, когда я попытаюсь получить доступ к атрибуту value()
этой аннотации @XmlJavaTypeAdapters
, Javassist сообщает мне, что значение по умолчанию отсутствует. А?
Другими словами, это прекрасно — действительно есть не — но я указал, что я надеялся, было то, что есть, не следует использовать массив нулевой длины (значение по умолчанию, мой явно указан нулевой длины массива следует использовать вместо этого:
final List<Object> annotations = java.util.Arrays.asList(packageInfoClass.getAnnotations());
for (final Object a : annotations) {
System.out.println("*** class annotation: " + a); // OK; one of these is @XmlJavaTypeAdapters
System.out.println(" ...of type: " + a.getClass()); // OK; resolves to XmlJavaTypeAdapters
System.out.println(" ...assignable to java.lang.annotation.Annotation? " + java.lang.annotation.Annotation.class.isInstance(a)); // OK; returns true
if (a instanceof XmlJavaTypeAdapters) {
final XmlJavaTypeAdapters x = (XmlJavaTypeAdapters)a;
System.out.println(" ...value: " + java.util.Arrays.asList(x.value())); // XXX x.value() throws an exception
}
}
Так почему же Javassist ищет значение по умолчанию в этом случае?
Моя более крупная проблема, конечно, относится к этому (к сожалению, довольно общему) случаю, где @XmlJavaTypeAdapters
указан без дополнительной информации. Мне нужно добавить значение члена value
, которое может содержать массив аннотаций @XmlJavaTypeAdapter
. Я не могу понять, как это сделать с Джавасистом. Как всегда, вся помощь ценится.