Support abstract, bridge, & interface methods in AnnotatedElementUtils
This commit introduces support for finding annotations on abstract, bridge, and interface methods in AnnotatedElementUtils. - Introduced dedicated findAnnotationAttributes() methods in AnnotatedElementUtils that provide first-class support for processing methods, class hierarchies, interfaces, bridge methods, etc. - Introduced find/get search algorithm dichotomy in AnnotatedElementUtils which is visible in the public API as well as in the internal implementation. This was necessary in order to maintain backwards compatibility with the existing API (even though it was undocumented). - Reverted all recent changes made to the "get semantics" search algorithm in AnnotatedElementUtils in order to ensure backwards compatibility, and reverted recent changes to JtaTransactionAnnotationParser and SpringTransactionAnnotationParser accordingly. - Documented internal AnnotatedElementUtils.Processor<T> interface. - Enabled failing tests and introduced findAnnotationAttributesFromBridgeMethod() test in AnnotatedElementUtilsTests. - Refactored ApplicationListenerMethodAdapter.getCondition() and enabled failing test in TransactionalEventListenerTests. - AnnotationUtils.isInterfaceWithAnnotatedMethods() is now package private. Issue: SPR-12738, SPR-11514, SPR-11598
This commit is contained in:
@@ -126,54 +126,6 @@ public class AnnotatedElementUtilsTests {
|
||||
attributes.getBoolean("readOnly"));
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnInheritedAnnotationInterface() {
|
||||
String name = Transactional.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(InheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Transactional on InheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnSubInheritedAnnotationInterface() {
|
||||
String name = Transactional.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(SubInheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Transactional on SubInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnSubSubInheritedAnnotationInterface() {
|
||||
String name = Transactional.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(SubSubInheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Transactional on SubSubInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnNonInheritedAnnotationInterface() {
|
||||
String name = Order.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(NonInheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Order on NonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnSubNonInheritedAnnotationInterface() {
|
||||
String name = Order.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(SubNonInheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Order on SubNonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnSubSubNonInheritedAnnotationInterface() {
|
||||
String name = Order.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(SubSubNonInheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should find @Order on SubSubNonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
// TODO [SPR-11598] Enable test.
|
||||
@Ignore("Disabled until SPR-11598 is resolved")
|
||||
@Test
|
||||
@@ -183,37 +135,126 @@ public class AnnotatedElementUtilsTests {
|
||||
assertNotNull("Should find @Transactional on ConcreteClassWithInheritedAnnotation", attributes);
|
||||
}
|
||||
|
||||
// TODO [SPR-12738] Enable test.
|
||||
@Ignore("Disabled until SPR-12738 is resolved")
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesInheritedFromInterfaceMethod() throws NoSuchMethodException {
|
||||
String name = Order.class.getName();
|
||||
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleFromInterface");
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(method, name);
|
||||
assertNotNull("Should find @Order on ConcreteClassWithInheritedAnnotation.handleFromInterface() method",
|
||||
attributes);
|
||||
public void getAnnotationAttributesOnInheritedAnnotationInterface() {
|
||||
String name = Transactional.class.getName();
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(InheritedAnnotationInterface.class, name);
|
||||
assertNotNull("Should get @Transactional on InheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
// TODO [SPR-12738] Enable test.
|
||||
@Ignore("Disabled until SPR-12738 is resolved")
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesInheritedFromAbstractMethod() throws NoSuchMethodException {
|
||||
String name = Transactional.class.getName();
|
||||
public void findAnnotationAttributesOnInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(InheritedAnnotationInterface.class, Transactional.class);
|
||||
assertNotNull("Should find @Transactional on InheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesOnSubInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(SubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertNotNull("Should find @Transactional on SubInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesOnSubSubInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(SubSubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertNotNull("Should find @Transactional on SubSubInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesOnNonInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(NonInheritedAnnotationInterface.class, Order.class);
|
||||
assertNotNull("Should find @Order on NonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void getAnnotationAttributesOnNonInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(NonInheritedAnnotationInterface.class, Order.class.getName());
|
||||
assertNotNull("Should get @Order on NonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesOnSubNonInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(SubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertNotNull("Should find @Order on SubNonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesOnSubSubNonInheritedAnnotationInterface() {
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(SubSubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertNotNull("Should find @Order on SubSubNonInheritedAnnotationInterface", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesInheritedFromInterfaceMethod() throws NoSuchMethodException {
|
||||
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleFromInterface");
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(method, Order.class);
|
||||
assertNotNull("Should find @Order on ConcreteClassWithInheritedAnnotation.handleFromInterface() method", attributes);
|
||||
}
|
||||
|
||||
/** @since 4.2 */
|
||||
@Test
|
||||
public void findAnnotationAttributesInheritedFromAbstractMethod() throws NoSuchMethodException {
|
||||
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handle");
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(method, name);
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(method, Transactional.class);
|
||||
assertNotNull("Should find @Transactional on ConcreteClassWithInheritedAnnotation.handle() method", attributes);
|
||||
}
|
||||
|
||||
// TODO [SPR-12738] Enable test.
|
||||
/**
|
||||
* TODO [SPR-12738] Enable test.
|
||||
*
|
||||
* <p>{@code AbstractClassWithInheritedAnnotation} declares {@code handleParameterized(T)}; whereas,
|
||||
* {@code ConcreteClassWithInheritedAnnotation} declares {@code handleParameterized(String)}.
|
||||
*
|
||||
* <p>Thus, this test fails because {@code AnnotatedElementUtils.processWithFindSemantics()}
|
||||
* does not resolve an equivalent method for {@code handleParameterized(String)}
|
||||
* in {@code AbstractClassWithInheritedAnnotation}.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
@Ignore("Disabled until SPR-12738 is resolved")
|
||||
@Test
|
||||
public void getAnnotationAttributesInheritedFromParameterizedMethod() throws NoSuchMethodException {
|
||||
String name = Transactional.class.getName();
|
||||
public void findAnnotationAttributesInheritedFromBridgedMethod() throws NoSuchMethodException {
|
||||
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleParameterized", String.class);
|
||||
AnnotationAttributes attributes = getAnnotationAttributes(method, name);
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(method, Transactional.class);
|
||||
assertNotNull("Should find @Transactional on ConcreteClassWithInheritedAnnotation.handleParameterized() method", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bridge/bridged method setup code copied from
|
||||
* {@link org.springframework.core.BridgeMethodResolverTests#testWithGenericParameter()}.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Test
|
||||
public void findAnnotationAttributesFromBridgeMethod() throws NoSuchMethodException {
|
||||
Method[] methods = StringGenericParameter.class.getMethods();
|
||||
Method bridgeMethod = null;
|
||||
Method bridgedMethod = null;
|
||||
for (Method method : methods) {
|
||||
if ("getFor".equals(method.getName()) && !method.getParameterTypes()[0].equals(Integer.class)) {
|
||||
if (method.getReturnType().equals(Object.class)) {
|
||||
bridgeMethod = method;
|
||||
}
|
||||
else {
|
||||
bridgedMethod = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(bridgeMethod != null && bridgeMethod.isBridge());
|
||||
assertTrue(bridgedMethod != null && !bridgedMethod.isBridge());
|
||||
|
||||
AnnotationAttributes attributes = findAnnotationAttributes(bridgeMethod, Order.class);
|
||||
assertNotNull("Should find @Order on StringGenericParameter.getFor() method", attributes);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@@ -349,6 +390,26 @@ public class AnnotatedElementUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
public static interface GenericParameter<T> {
|
||||
|
||||
T getFor(Class<T> cls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class StringGenericParameter implements GenericParameter<String> {
|
||||
|
||||
@Order
|
||||
@Override
|
||||
public String getFor(Class<String> cls) {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public String getFor(Integer integer) {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static interface InheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user