1

我正在使用Javassistpackage-info在“类”上添加和修改注释。

在某些情况下,我需要处理以下边缘情况。有人(错误地)@XmlJavaTypeAdapters在包上指定了注释package-info,但没有提供value属性(定义为 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);
}

在上面的代码片段中,我创建了一个新的成员值来保存一个注释数组,因为 of 的value()属性@XmlJavaTypeAdapters是一个@XmlJavaTypeAdapter. 我已经通过尝试预测类似 Zen 的文档的意图来指定它的数组类型——似乎如果你提供另一个MemberValue,它MemberValue会以某种方式作为数组的类型。在我的情况下,我希望数组的类型是@XmlJavaTypeAdapter,这是一个注释,所以唯一MemberValue合适的类型是AnnotationMemberValue. 所以我创建了一个空的并将其设置为数组类型。

只要您保持“在”Javassist 之内,就可以正常工作。

然而,似乎出了点问题。如果我要求 Javassist 将其所有专有注解转换为真正java.lang.annotation.Annotation的 Java,那么当我尝试访问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我似乎无法弄清楚如何使用 Javassist 来实现这一点。一如既往,所有帮助表示赞赏。

4

1 回答 1

2

对于后代,似乎在这种特殊情况下(为了避免 aNullPointerException和/或 a 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 黑客。

于 2011-12-31T16:31:48.570 回答