Consistent detection of Order annotation in superclasses and interfaces

Issue: SPR-10514
This commit is contained in:
Juergen Hoeller 2013-05-16 18:05:56 +02:00
parent 16548d23e9
commit 814d24e64f
6 changed files with 42 additions and 20 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.aop.aspectj.annotation;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -109,7 +110,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) { if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder(); return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
} }
Order order = type.getAnnotation(Order.class); Order order = AnnotationUtils.findAnnotation(type, Order.class);
if (order != null) { if (order != null) {
return order.value(); return order.value();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory; import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
/** /**
@ -59,7 +60,7 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
*/ */
@Override @Override
protected int getOrderForAspectClass(Class<?> aspectClass) { protected int getOrderForAspectClass(Class<?> aspectClass) {
Order order = aspectClass.getAnnotation(Order.class); Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
if (order != null) { if (order != null) {
return order.value(); return order.value();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory; import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
/** /**
@ -60,7 +61,7 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
*/ */
@Override @Override
protected int getOrderForAspectClass(Class<?> aspectClass) { protected int getOrderForAspectClass(Class<?> aspectClass) {
Order order = aspectClass.getAnnotation(Order.class); Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
if (order != null) { if (order != null) {
return order.value(); return order.value();
} }

View File

@ -51,7 +51,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
} }
if (obj != null) { if (obj != null) {
Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass()); Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass());
Order order = clazz.getAnnotation(Order.class); Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
if (order != null) { if (order != null) {
return order.value(); return order.value();
} }

View File

@ -19,7 +19,6 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@ -121,24 +120,24 @@ public abstract class AnnotationUtils {
*/ */
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) { public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
A annotation = getAnnotation(method, annotationType); A annotation = getAnnotation(method, annotationType);
Class<?> cl = method.getDeclaringClass(); Class<?> clazz = method.getDeclaringClass();
if (annotation == null) { if (annotation == null) {
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces()); annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
} }
while (annotation == null) { while (annotation == null) {
cl = cl.getSuperclass(); clazz = clazz.getSuperclass();
if (cl == null || cl == Object.class) { if (clazz == null || clazz.equals(Object.class)) {
break; break;
} }
try { try {
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes()); Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
annotation = getAnnotation(equivalentMethod, annotationType); annotation = getAnnotation(equivalentMethod, annotationType);
} }
catch (NoSuchMethodException ex) { catch (NoSuchMethodException ex) {
// No equivalent method found // No equivalent method found
} }
if (annotation == null) { if (annotation == null) {
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces()); annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
} }
} }
return annotation; return annotation;
@ -217,7 +216,7 @@ public abstract class AnnotationUtils {
} }
} }
Class<?> superClass = clazz.getSuperclass(); Class<?> superClass = clazz.getSuperclass();
if (superClass == null || superClass == Object.class) { if (superClass == null || superClass.equals(Object.class)) {
return null; return null;
} }
return findAnnotation(superClass, annotationType); return findAnnotation(superClass, annotationType);
@ -273,25 +272,22 @@ public abstract class AnnotationUtils {
* @return the first {@link Class} in the inheritance hierarchy of the specified * @return the first {@link Class} in the inheritance hierarchy of the specified
* {@code clazz} which declares an annotation of at least one of the specified * {@code clazz} which declares an annotation of at least one of the specified
* {@code annotationTypes}, or {@code null} if not found * {@code annotationTypes}, or {@code null} if not found
* @since 3.2.2
* @see Class#isAnnotationPresent(Class) * @see Class#isAnnotationPresent(Class)
* @see Class#getDeclaredAnnotations() * @see Class#getDeclaredAnnotations()
* @see #findAnnotationDeclaringClass(Class, Class) * @see #findAnnotationDeclaringClass(Class, Class)
* @see #isAnnotationDeclaredLocally(Class, Class) * @see #isAnnotationDeclaredLocally(Class, Class)
* @since 3.2.2
*/ */
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, Class<?> clazz) {
Class<?> clazz) {
Assert.notEmpty(annotationTypes, "The list of annotation types must not be empty"); Assert.notEmpty(annotationTypes, "The list of annotation types must not be empty");
if (clazz == null || clazz.equals(Object.class)) { if (clazz == null || clazz.equals(Object.class)) {
return null; return null;
} }
for (Class<? extends Annotation> annotationType : annotationTypes) { for (Class<? extends Annotation> annotationType : annotationTypes) {
if (isAnnotationDeclaredLocally(annotationType, clazz)) { if (isAnnotationDeclaredLocally(annotationType, clazz)) {
return clazz; return clazz;
} }
} }
return findAnnotationDeclaringClassForTypes(annotationTypes, clazz.getSuperclass()); return findAnnotationDeclaringClassForTypes(annotationTypes, clazz.getSuperclass());
} }

View File

@ -45,6 +45,16 @@ public class AnnotationAwareOrderComparatorTests {
assertTrue(list.get(1) instanceof B); assertTrue(list.get(1) instanceof B);
} }
@Test
public void sortInstancesWithSubclass() {
List<Object> list = new ArrayList<>();
list.add(new B());
list.add(new C());
AnnotationAwareOrderComparator.sort(list);
assertTrue(list.get(0) instanceof C);
assertTrue(list.get(1) instanceof B);
}
@Test @Test
public void sortClasses() { public void sortClasses() {
List<Object> list = new ArrayList<>(); List<Object> list = new ArrayList<>();
@ -55,6 +65,16 @@ public class AnnotationAwareOrderComparatorTests {
assertEquals(B.class, list.get(1)); assertEquals(B.class, list.get(1));
} }
@Test
public void sortClassesWithSubclass() {
List<Object> list = new ArrayList<>();
list.add(B.class);
list.add(C.class);
AnnotationAwareOrderComparator.sort(list);
assertEquals(C.class, list.get(0));
assertEquals(B.class, list.get(1));
}
@Order(1) @Order(1)
private static class A { private static class A {
@ -64,4 +84,7 @@ public class AnnotationAwareOrderComparatorTests {
private static class B { private static class B {
} }
private static class C extends A {
}
} }