gpt4 book ai didi

java - 无法使用 Java 8 修改 package-info.java 的注解

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:53:14 30 4
gpt4 key购买 nike

我遇到了一个问题,我必须修改一个包信息。

包信息.java

@javax.xml.bind.annotation.XmlSchema(namespace = "http://some.url/soap/style/document_literal")
package org.example.wsdl.wsdl;

以下代码适用于 1.7.0_45。

//          do not load any classes before, this could break the following code.
Class<?> pkgInfo = Class.forName("org.example.wsdl.package-info", true, NameSpaceModifier.class.getClassLoader());
Field field = Class.class.getDeclaredField("annotations");
field.setAccessible(true);

final XmlSchema oldAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0];
logger.debug("Old Annotation namespace value was: " + oldAnnotation.namespace());
XmlSchema newAnnotation = new XmlSchema() {

@Override
public XmlNs[] xmlns() {
return oldAnnotation.xmlns();
}

@Override
public String namespace() {
return "newNs";
}

@Override
public XmlNsForm elementFormDefault() {
return oldAnnotation.elementFormDefault();
}

@Override
public XmlNsForm attributeFormDefault() {
return oldAnnotation.attributeFormDefault();
}

@Override
public String location() {
return oldAnnotation.location();
}

@Override
public Class<? extends Annotation> annotationType() {
return oldAnnotation.annotationType();
}
};

@SuppressWarnings("unchecked")
Map<Class<? extends Annotation>, Annotation> annotations = (Map<Class<? extends Annotation>, Annotation>) field.get(pkgInfo);
annotations.put(XmlSchema.class, newAnnotation);

XmlSchema modifiedAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0];

当使用 1.8.0_05 编译和执行相同代码时,我收到此错误消息:

java.lang.NoSuchFieldException: annotations
at java.lang.Class.getDeclaredField(Class.java:2057)

我知道这是一个 Hack,至少它看起来像一个。但是 Java 8 是否按预期在这里工作?那么我必须如何更改适用于 Java 8 的代码?

也欢迎 Javasist 回答 ;)

最佳答案

Java 8 改变了注释在内部的存储方式。由于您正在使用带有硬编码字段名称的讨厌的反射 hack,因此任何 Java 更新都有可能重新破坏您的代码。

java.lang.Class:

/**
* @since 1.5
*/
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}

private volatile transient AnnotationData annotationData;

private AnnotationData annotationData() {
while (true) { // retry loop
AnnotationData annotationData = this.annotationData;
int classRedefinedCount = this.classRedefinedCount;
if (annotationData != null &&
annotationData.redefinedCount == classRedefinedCount) {
return annotationData;
}
// null or stale annotationData -> optimistically create new instance
AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);
// try to install it
if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {
// successfully installed new AnnotationData
return newAnnotationData;
}
}
}

private static class AnnotationData {
final Map<Class<? extends Annotation>, Annotation> annotations;
final Map<Class<? extends Annotation>, Annotation> declaredAnnotations;

// Value of classRedefinedCount when we created this AnnotationData instance
final int redefinedCount;

AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations,
Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
int redefinedCount) {
this.annotations = annotations;
this.declaredAnnotations = declaredAnnotations;
this.redefinedCount = redefinedCount;
}
}

我想您可以使用新的字段值来临时修复您的代码。永久修复是更改注释本身,而不是在运行时动态修改它。

Field annotationDataField = Class.class.getDeclaredField("annotationData");
annotationDataField.setAccessible(true);

Object annotationData = annotationDataField.get(pkgInfo);

Field annotationsField = annotationData.getClass().getDeclaredField("annotations");
annotationsField.setAccessible(true);

Map<Class<? extends Annotation>, Annotation> annotations = (Map<Class<? extends Annotation>, Annotation>) annotationsField
.get(annotationData);
annotations.put(XmlSchema.class, newAnnotation);

XmlSchema modifiedAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0];

关于java - 无法使用 Java 8 修改 package-info.java 的注解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24539574/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com