Fix annotation search ending too early

In AnnotationUtils#findAnnotation(Method, Class), the search for a
method annotation fails if:

 - the original method does not have the annotation

 - an abstract superclass does not have an equivalent method declared

 - an interface implemented by the superclass has the method and
   the annotation -> this should be found, but is not!

This happens because the try-catch block in #findAnnotation is too wide:
cl.getDeclaredMethod() can throw NoSuchMethodException and skip the
'#searchOnInterfaces' call prematurely.

The try-catch block was made narrower to allow #searchOnInterfaces to
be called even if the abstract class does not have the method declared
at all.

Issue: SPR-9342
This commit is contained in:
Petr Janecek 2012-05-16 22:05:59 +02:00 committed by Chris Beams
parent 6023b2060b
commit ef7e728bb8
2 changed files with 27 additions and 22 deletions

View File

@ -132,12 +132,12 @@ public abstract class AnnotationUtils {
try {
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
annotation = getAnnotation(equivalentMethod, annotationType);
if (annotation == null) {
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
}
}
catch (NoSuchMethodException ex) {
// We're done...
// No equivalent method found
}
if (annotation == null) {
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
}
}
return annotation;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,32 +16,20 @@
package org.springframework.core.annotation;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotationDeclaringClass;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotation;
import static org.springframework.core.annotation.AnnotationUtils.isAnnotationDeclaredLocally;
import static org.springframework.core.annotation.AnnotationUtils.isAnnotationInherited;
import java.io.IOException;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.core.Ordered;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Component;
import static org.junit.Assert.*;
import static org.springframework.core.annotation.AnnotationUtils.*;
/**
* @author Rod Johnson
* @author Juergen Hoeller
@ -219,6 +207,14 @@ public class AnnotationUtilsTests {
assertNotNull(order);
}
@Test
public void testFindAnnotationFromInterfaceWhenSuperDoesNotImplementMethod() throws Exception {
Method method = SubOfAbstractImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
Order order = findAnnotation(method, Order.class);
assertNotNull(order);
}
@Component(value="meta1")
@Retention(RetentionPolicy.RUNTIME)
@ -353,6 +349,15 @@ public class AnnotationUtilsTests {
}
}
public abstract static class AbstractDoesNotImplementInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod {
}
public static class SubOfAbstractImplementsInterfaceWithAnnotatedMethod extends AbstractDoesNotImplementInterfaceWithAnnotatedMethod {
public void foo() {
}
}
}
@Retention(RetentionPolicy.RUNTIME)