无法使用Java 8修改package-info.java的注释
发布时间:2020-12-15 03:04:41 所属栏目:Java 来源:网络整理
导读:我正面临一个问题,我必须修改包信息. package-info.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,th
|
我正面临一个问题,我必须修改包信息.
package-info.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)
我知道它是一个哈克,至少它看起来像一个.但Java 8是否按预期工作? Javassist的答案也很受欢迎;) 解决方法
Java 8改变了内部存储注释的方式.由于您使用的是具有硬编码字段名称的恶意反射黑客,因此任何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>) annotationsField
.get(annotationData);
annotations.put(XmlSchema.class,newAnnotation);
XmlSchema modifiedAnnotation = (XmlSchema) pkgInfo.getAnnotations()[0];
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |








