AnnotationUtils defensively catches unexpected exceptions from retrieval attempts (proceeding like the annotation wasn't there)
This is analogous to what the JVM does for cases where the annotation type itself isn't present on the classpath. We're effectively extending that policy to values referenced within an annotation declaration. Issue: SPR-11874
This commit is contained in:
@@ -79,7 +79,14 @@ public abstract class AnnotationUtils {
|
|||||||
if (annotationType.isInstance(ann)) {
|
if (annotationType.isInstance(ann)) {
|
||||||
return (T) ann;
|
return (T) ann;
|
||||||
}
|
}
|
||||||
return ann.annotationType().getAnnotation(annotationType);
|
try {
|
||||||
|
return ann.annotationType().getAnnotation(annotationType);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,16 +99,23 @@ public abstract class AnnotationUtils {
|
|||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
|
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
|
||||||
T ann = ae.getAnnotation(annotationType);
|
try {
|
||||||
if (ann == null) {
|
T ann = ae.getAnnotation(annotationType);
|
||||||
for (Annotation metaAnn : ae.getAnnotations()) {
|
if (ann == null) {
|
||||||
ann = metaAnn.annotationType().getAnnotation(annotationType);
|
for (Annotation metaAnn : ae.getAnnotations()) {
|
||||||
if (ann != null) {
|
ann = metaAnn.annotationType().getAnnotation(annotationType);
|
||||||
break;
|
if (ann != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ann;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return ann;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +126,14 @@ public abstract class AnnotationUtils {
|
|||||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
|
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
|
||||||
*/
|
*/
|
||||||
public static Annotation[] getAnnotations(Method method) {
|
public static Annotation[] getAnnotations(Method method) {
|
||||||
return BridgeMethodResolver.findBridgedMethod(method).getAnnotations();
|
try {
|
||||||
|
return BridgeMethodResolver.findBridgedMethod(method).getAnnotations();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,10 +183,16 @@ public abstract class AnnotationUtils {
|
|||||||
public static <A extends Annotation> Set<A> getRepeatableAnnotation(AnnotatedElement annotatedElement,
|
public static <A extends Annotation> Set<A> getRepeatableAnnotation(AnnotatedElement annotatedElement,
|
||||||
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
|
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
|
||||||
|
|
||||||
if (annotatedElement.getAnnotations().length == 0) {
|
try {
|
||||||
return Collections.emptySet();
|
if (annotatedElement.getAnnotations().length > 0) {
|
||||||
|
return new AnnotationCollector<A>(containerAnnotationType, annotationType).getResult(annotatedElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new AnnotationCollector<A>(containerAnnotationType, annotationType).getResult(annotatedElement);
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
}
|
||||||
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,9 +257,15 @@ public abstract class AnnotationUtils {
|
|||||||
}
|
}
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Method ifcMethod : iface.getMethods()) {
|
for (Method ifcMethod : iface.getMethods()) {
|
||||||
if (ifcMethod.getAnnotations().length > 0) {
|
try {
|
||||||
found = true;
|
if (ifcMethod.getAnnotations().length > 0) {
|
||||||
break;
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
annotatedInterfaceCache.put(iface, found);
|
annotatedInterfaceCache.put(iface, found);
|
||||||
@@ -278,7 +311,14 @@ public abstract class AnnotationUtils {
|
|||||||
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
|
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
|
||||||
Assert.notNull(clazz, "Class must not be null");
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||||
return clazz.getAnnotation(annotationType);
|
try {
|
||||||
|
return clazz.getAnnotation(annotationType);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (Class<?> ifc : clazz.getInterfaces()) {
|
for (Class<?> ifc : clazz.getInterfaces()) {
|
||||||
A annotation = findAnnotation(ifc, annotationType, visited);
|
A annotation = findAnnotation(ifc, annotationType, visited);
|
||||||
@@ -390,12 +430,18 @@ public abstract class AnnotationUtils {
|
|||||||
Assert.notNull(annotationType, "Annotation type must not be null");
|
Assert.notNull(annotationType, "Annotation type must not be null");
|
||||||
Assert.notNull(clazz, "Class must not be null");
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
boolean declaredLocally = false;
|
boolean declaredLocally = false;
|
||||||
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
|
try {
|
||||||
if (annotation.annotationType().equals(annotationType)) {
|
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
|
||||||
declaredLocally = true;
|
if (annotation.annotationType().equals(annotationType)) {
|
||||||
break;
|
declaredLocally = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Assuming nested Class values not resolvable within annotation attributes...
|
||||||
|
// We're probably hitting a non-present optional arrangement - let's back out.
|
||||||
|
}
|
||||||
return declaredLocally;
|
return declaredLocally;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +678,7 @@ public abstract class AnnotationUtils {
|
|||||||
this.result.add((A) annotation);
|
this.result.add((A) annotation);
|
||||||
}
|
}
|
||||||
else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) {
|
else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) {
|
||||||
this.result.addAll(Arrays.asList(getValue(annotation)));
|
this.result.addAll(getValue(annotation));
|
||||||
}
|
}
|
||||||
else if (!isInJavaLangAnnotationPackage(annotation)) {
|
else if (!isInJavaLangAnnotationPackage(annotation)) {
|
||||||
process(annotation.annotationType());
|
process(annotation.annotationType());
|
||||||
@@ -642,15 +688,15 @@ public abstract class AnnotationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private A[] getValue(Annotation annotation) {
|
private List<A> getValue(Annotation annotation) {
|
||||||
try {
|
try {
|
||||||
Method method = annotation.annotationType().getDeclaredMethod("value");
|
Method method = annotation.annotationType().getDeclaredMethod("value");
|
||||||
ReflectionUtils.makeAccessible(method);
|
ReflectionUtils.makeAccessible(method);
|
||||||
return (A[]) method.invoke(annotation);
|
return Arrays.asList((A[]) method.invoke(annotation));
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new IllegalStateException("Unable to read value from repeating annotation container " +
|
// Unable to read value from repeating annotation container -> ignore it.
|
||||||
this.containerAnnotationType.getName(), ex);
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user