我正在使用Javassist在package-info
“类”上添加和修改注释。
在某些情况下,我需要处理以下边缘情况。有人(错误地)在@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()
的{{1}}属性是@XmlJavaTypeAdapters
的数组。我已经通过尝试神圣类似Zen文档的意图来指定它的数组类型 - 似乎如果你提供另一个@XmlJavaTypeAdapter
,那么MemberValue
将以某种方式作为数组的类型。在我的情况下,我希望数组的类型为MemberValue
,这是一个注释,因此唯一合适的@XmlJavaTypeAdapter
类型是MemberValue
。所以我创建了一个空的,并将其设置为数组类型。
只要你留在“Javassist”中,这就可以正常工作。
但是,似乎出现了问题。如果我要求Javassist将其所有专有注释转换为真正的Java AnnotationMemberValue
,那么当我尝试访问此java.lang.annotation.Annotation
注释的value()
属性时,Javassist告诉我没有默认值。咦?
换句话说,那很好 - 确实没有 - 但是我已经指定了我所希望的零长度数组(也就是说,不应该使用默认值;我明确指定的零长度数组应该改为使用):
@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
}
}
被指定而没有关于它的进一步信息。我需要添加一个@XmlJavaTypeAdapters
成员值,该值可以包含value
个注释数组。我似乎无法弄清楚如何使用Javassist实现这一目标。一如往常,所有帮助表示赞赏。
答案 0 :(得分:2)
对于后代,似乎在这种特殊情况下(为了避免使用NullPointerException
和/或RuntimeException
),您需要这样做:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(constantPool);
amv.setValue(new AnnotationMemberValue[0]);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
特别注意,在构建ArrayMemberValue
时,我故意省略数组类型(包括任何类型之一都会导致异常)。然后我将其值显式设置为类型为AnnotationMemberValue
的空数组。此处的任何其他组合都将导致异常。
此外,非常奇怪的是,if
块中的最后一行非常重要。即使在这种特殊情况下,注释本身也被找到了,因此AnnotationsAttribute
已经存在,必须重新添加。如果不这样做,您将收到RuntimeException
抱怨缺少默认值的信息。
我希望这有助于其他Javassist黑客。