From c6d29f1a314c600c6b2d1cdfc3a21ba66523b037 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 4 Sep 2014 00:41:13 +0200 Subject: [PATCH] Refactored support for @Order on @Bean methods as well as @Priority handling Issue: SPR-11310 Issue: SPR-10548 --- .../support/DefaultDependencyComparator.java | 61 -------- .../support/DefaultListableBeanFactory.java | 77 ++++++---- .../support/FactoryAwareOrderProvider.java | 87 ----------- .../DefaultListableBeanFactoryTests.java | 8 + ...wiredAnnotationBeanPostProcessorTests.java | 42 +----- .../support/DependencyComparatorTests.java | 68 --------- .../FactoryAwareOrderProviderTests.java | 137 ------------------ .../annotation/AnnotationConfigUtils.java | 4 +- .../{spr11310 => }/Spr11310Tests.java | 3 +- .../springframework/core/OrderComparator.java | 91 +++++++++++- .../AnnotationAwareOrderComparator.java | 69 +++++++-- .../DefaultOrderProviderComparator.java | 71 --------- .../core/annotation/OrderProvider.java | 36 ----- .../annotation/OrderProviderComparator.java | 49 ------- .../core/annotation/OrderUtils.java | 16 +- ...sts.java => OrderSourceProviderTests.java} | 119 ++++++++------- .../core/annotation/OrderUtilsTests.java | 4 +- 17 files changed, 281 insertions(+), 661 deletions(-) delete mode 100644 spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultDependencyComparator.java delete mode 100644 spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryAwareOrderProvider.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/DependencyComparatorTests.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/FactoryAwareOrderProviderTests.java rename spring-context/src/test/java/org/springframework/context/annotation/{spr11310 => }/Spr11310Tests.java (97%) delete mode 100644 spring-core/src/main/java/org/springframework/core/annotation/DefaultOrderProviderComparator.java delete mode 100644 spring-core/src/main/java/org/springframework/core/annotation/OrderProvider.java delete mode 100644 spring-core/src/main/java/org/springframework/core/annotation/OrderProviderComparator.java rename spring-core/src/test/java/org/springframework/core/annotation/{DefaultOrderProviderComparatorTests.java => OrderSourceProviderTests.java} (69%) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultDependencyComparator.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultDependencyComparator.java deleted file mode 100644 index d6e396c79248..000000000000 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultDependencyComparator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import java.util.Comparator; - -import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.core.annotation.DefaultOrderProviderComparator; - -/** - * The default {@link Comparator} to use to order dependencies. Extends from - * {@link DefaultOrderProviderComparator} so that the bean factory has the ability - * to provide an {@link org.springframework.core.annotation.OrderProvider} that - * is aware of more bean metadata, if any. - * - * @author Stephane Nicoll - * @since 4.1 - * @see org.springframework.core.annotation.OrderProviderComparator - * @see org.springframework.core.annotation.OrderProvider - * @see DefaultListableBeanFactory#setDependencyComparator(java.util.Comparator) - */ -public class DefaultDependencyComparator extends DefaultOrderProviderComparator implements Comparator { - - /** - * Shared default instance of DefaultDependencyComparator. - */ - public static final DefaultDependencyComparator INSTANCE = new DefaultDependencyComparator(); - - - private final Comparator comparator; - - - public DefaultDependencyComparator() { - this.comparator = AnnotationAwareOrderComparator.INSTANCE; - } - - public DefaultDependencyComparator(Comparator comparator) { - this.comparator = comparator; - } - - - @Override - public int compare(Object o1, Object o2) { - return this.comparator.compare(o1, o2); - } - -} diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 1f14df139e12..843ae4b80aee 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -24,6 +24,7 @@ import java.lang.annotation.Annotation; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; @@ -62,9 +63,8 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.core.OrderComparator; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.OrderProviderComparator; -import org.springframework.core.annotation.OrderUtils; import org.springframework.lang.UsesJava8; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -941,7 +941,7 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (this.dependencyComparator != null && result instanceof Object[]) { - sortArray((Object[]) result, matchingBeans); + Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans)); } return result; } @@ -968,7 +968,7 @@ else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (this.dependencyComparator != null && result instanceof List) { - sortList((List) result, matchingBeans); + Collections.sort((List) result, adaptDependencyComparator(matchingBeans)); } return result; } @@ -1029,32 +1029,22 @@ else if (Map.class.isAssignableFrom(type) && type.isInterface()) { } } - private void sortArray(Object[] items, Map matchingBeans) { - if (this.dependencyComparator instanceof OrderProviderComparator) { - ((OrderProviderComparator) this.dependencyComparator) - .sortArray(items, createFactoryAwareOrderProvider(matchingBeans)); + private Comparator adaptDependencyComparator(Map matchingBeans) { + if (this.dependencyComparator instanceof OrderComparator) { + return ((OrderComparator) this.dependencyComparator).withSourceProvider( + createFactoryAwareOrderSourceProvider(matchingBeans)); } else { - Arrays.sort(items, this.dependencyComparator); + return this.dependencyComparator; } } - private void sortList(List items, Map matchingBeans) { - if (this.dependencyComparator instanceof OrderProviderComparator) { - ((OrderProviderComparator) this.dependencyComparator) - .sortList(items, createFactoryAwareOrderProvider(matchingBeans)); - } - else { - Collections.sort(items, this.dependencyComparator); - } - } - - private FactoryAwareOrderProvider createFactoryAwareOrderProvider(Map beans) { + private FactoryAwareOrderSourceProvider createFactoryAwareOrderSourceProvider(Map beans) { IdentityHashMap instancesToBeanNames = new IdentityHashMap(); for (Map.Entry entry : beans.entrySet()) { instancesToBeanNames.put(entry.getValue(), entry.getKey()); } - return new FactoryAwareOrderProvider(instancesToBeanNames, this); + return new FactoryAwareOrderSourceProvider(instancesToBeanNames); } /** @@ -1223,13 +1213,18 @@ protected boolean isPrimary(String beanName, Object beanInstance) { /** * Return the priority assigned for the given bean instance by * the {@code javax.annotation.Priority} annotation. - *

If the annotation is not present, returns {@code null}. - * @param beanInstance the bean instance to check (can be null) + *

The default implementation delegates to the specified + * {@link #setDependencyComparator dependency comparator}, checking its + * {@link OrderComparator#getPriority method} if it is an extension of + * Spring's common {@link OrderComparator} - typically, an + * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator}. + * If no such comparator is present, this implementation returns {@code null}. + * @param beanInstance the bean instance to check (can be {@code null}) * @return the priority assigned to that bean or {@code null} if none is set */ protected Integer getPriority(Object beanInstance) { - if (beanInstance != null) { - return OrderUtils.getPriorityValue(beanInstance.getClass()); + if (this.dependencyComparator instanceof OrderComparator) { + return ((OrderComparator) this.dependencyComparator).getPriority(beanInstance); } return null; } @@ -1406,4 +1401,36 @@ public Object createDependencyProvider(DependencyDescriptor descriptor, String b } } + + /** + * An {@link org.springframework.core.OrderComparator.OrderSourceProvider} implementation + * that is aware of the bean metadata of the instances to sort. + *

Lookup for the method factory of an instance to sort, if any, and let the + * comparator retrieve the {@link org.springframework.core.annotation.Order} + * value defined on it. This essentially allows for the following construct: + */ + private class FactoryAwareOrderSourceProvider implements OrderComparator.OrderSourceProvider { + + private final Map instancesToBeanNames; + + public FactoryAwareOrderSourceProvider(Map instancesToBeanNames) { + this.instancesToBeanNames = instancesToBeanNames; + } + + @Override + public Object getOrderSource(Object obj) { + return getFactoryMethod(this.instancesToBeanNames.get(obj)); + } + + private Method getFactoryMethod(String beanName) { + if (beanName != null && containsBeanDefinition(beanName)) { + BeanDefinition bd = getMergedBeanDefinition(beanName); + if (bd instanceof RootBeanDefinition) { + return ((RootBeanDefinition) bd).getResolvedFactoryMethod(); + } + } + return null; + } + } + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryAwareOrderProvider.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryAwareOrderProvider.java deleted file mode 100644 index d1578d85a170..000000000000 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryAwareOrderProvider.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import java.lang.reflect.Method; -import java.util.Map; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.Order; -import org.springframework.core.annotation.OrderProvider; - -/** - * An {@link OrderProvider} implementation that is aware of the - * bean metadata of the instances to sort. - * - *

Lookup for the method factory of an instance to sort, if - * any and retrieve the {@link Order} value defined on it. This - * essentially allows for the following construct: - * - *

- * @Configuration
- * public class AppConfig {
- *
- *     @Bean
- *     @Order(5)
- *     public MyService myService() {
- *         return new MyService();
- *     }
- * }
- * - * @author Stephane Nicoll - * @since 4.1 - */ -class FactoryAwareOrderProvider implements OrderProvider { - - private final Map instancesToBeanNames; - - private final ConfigurableListableBeanFactory beanFactory; - - - public FactoryAwareOrderProvider(Map instancesToBeanNames, - ConfigurableListableBeanFactory beanFactory) { - - this.instancesToBeanNames = instancesToBeanNames; - this.beanFactory = beanFactory; - } - - - @Override - public Integer getOrder(Object obj) { - Method factoryMethod = getFactoryMethod(this.instancesToBeanNames.get(obj)); - if (factoryMethod != null) { - Order order = AnnotationUtils.getAnnotation(factoryMethod, Order.class); - if (order != null) { - return order.value(); - } - } - return null; - } - - private Method getFactoryMethod(String beanName) { - if (beanName != null && beanFactory.containsBeanDefinition(beanName)) { - BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName); - if (bd instanceof RootBeanDefinition) { - return ((RootBeanDefinition) bd).getResolvedFactoryMethod(); - } - } - return null; - } - -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 19770a646be8..cc20a212437f 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -69,6 +69,7 @@ import org.springframework.beans.factory.xml.ConstructorDependenciesBean; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; @@ -1392,6 +1393,7 @@ public void testGetBeanByTypeWithMultiplePrimary() throws Exception { @Test public void testGetBeanByTypeWithPriority() throws Exception { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class); lbf.registerBeanDefinition("bd1", bd1); @@ -1403,6 +1405,7 @@ public void testGetBeanByTypeWithPriority() throws Exception { @Test public void testGetBeanByTypeWithMultiplePriority() throws Exception { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class); lbf.registerBeanDefinition("bd1", bd1); @@ -1416,6 +1419,7 @@ public void testGetBeanByTypeWithMultiplePriority() throws Exception { @Test public void testGetBeanByTypeWithPriorityAndNullInstance() throws Exception { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(NullTestBeanFactoryBean.class); lbf.registerBeanDefinition("bd1", bd1); @@ -1427,6 +1431,7 @@ public void testGetBeanByTypeWithPriorityAndNullInstance() throws Exception { @Test public void testGetBeanByTypePrimaryHasPrecedenceOverPriority() throws Exception { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class); bd2.setPrimary(true); @@ -1697,6 +1702,7 @@ public void testAutowireBeanByTypeWithTwoPrimaryCandidates() { @Test public void testAutowireBeanByTypeWithTwoMatchesAndPriority() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class); lbf.registerBeanDefinition("test", bd); @@ -1710,6 +1716,7 @@ public void testAutowireBeanByTypeWithTwoMatchesAndPriority() { @Test public void testAutowireBeanByTypeWithIdenticalPriorityCandidates() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class); lbf.registerBeanDefinition("test", bd); @@ -1730,6 +1737,7 @@ public void testAutowireBeanByTypeWithIdenticalPriorityCandidates() { @Test public void testAutowireBeanByTypePrimaryTakesPrecedenceOverPriority() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class); RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class); bd2.setPrimary(true); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java index 13607b20f1da..87331f546902 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java @@ -39,11 +39,11 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.AutowireCandidateQualifier; -import org.springframework.beans.factory.support.DefaultDependencyComparator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.Ordered; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.Order; import org.springframework.tests.sample.beans.ITestBean; import org.springframework.tests.sample.beans.IndexedTestBean; @@ -354,7 +354,7 @@ public void testOptionalResourceInjectionWithNoDependencies() { @Test public void testOrderedResourceInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); @@ -385,38 +385,10 @@ public void testOrderedResourceInjection() { bf.destroySingletons(); } - @Test - public void testOrderedResourceInjectionDetectsFactoryAwareComparator() { - DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - DefaultDependencyComparator comparator = mock(DefaultDependencyComparator.class); - bf.setDependencyComparator(comparator); - - AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); - bpp.setBeanFactory(bf); - bf.addBeanPostProcessor(bpp); - bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(OptionalResourceInjectionBean.class)); - TestBean tb = new TestBean(); - bf.registerSingleton("testBean", tb); - IndexedTestBean itb = new IndexedTestBean(); - bf.registerSingleton("indexedTestBean", itb); - final OrderedNestedTestBean ntb1 = new OrderedNestedTestBean(); - ntb1.setOrder(2); - bf.registerSingleton("nestedTestBean1", ntb1); - final OrderedNestedTestBean ntb2 = new OrderedNestedTestBean(); - ntb2.setOrder(1); - bf.registerSingleton("nestedTestBean2", ntb2); - - OptionalResourceInjectionBean bean = (OptionalResourceInjectionBean) bf.getBean("annotatedBean"); - verify(comparator, never()).compare(any(), any()); - verify(comparator, never()).sortList(any(),any()); - verify(comparator, times(2)).sortArray(any(),any()); - bf.destroySingletons(); - } - @Test public void testAnnotationOrderedResourceInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); @@ -448,7 +420,7 @@ public void testAnnotationOrderedResourceInjection() { @Test public void testOrderedCollectionResourceInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); @@ -489,7 +461,7 @@ public void testOrderedCollectionResourceInjection() { @Test public void testAnnotationOrderedCollectionResourceInjection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); @@ -607,7 +579,7 @@ public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() @Test public void testConstructorResourceInjectionWithMultipleOrderedCandidates() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); @@ -631,7 +603,7 @@ public void testConstructorResourceInjectionWithMultipleOrderedCandidates() { @Test public void testConstructorResourceInjectionWithMultipleCandidatesAsOrderedCollection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - bf.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(bf); bf.addBeanPostProcessor(bpp); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/DependencyComparatorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/DependencyComparatorTests.java deleted file mode 100644 index e9ea18af9393..000000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/DependencyComparatorTests.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -import org.springframework.core.Ordered; - -/** - * - * @author Stephane Nicoll - */ -public class DependencyComparatorTests { - - private final DefaultDependencyComparator comparator = new DefaultDependencyComparator(); - - @Test - public void plainComparator() { - List items = new ArrayList(); - C c = new C(5); - C c2 = new C(-5); - items.add(c); - items.add(c2); - Collections.sort(items, comparator); - assertOrder(items, c2, c); - } - - private void assertOrder(List actual, Object... expected) { - for (int i = 0; i < actual.size(); i++) { - assertSame("Wrong instance at index '" + i + "'", expected[i], actual.get(i)); - } - assertEquals("Wrong number of items", expected.length, actual.size()); - } - - private static class C implements Ordered { - private final int order; - - private C(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return order; - } - } - -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/FactoryAwareOrderProviderTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/FactoryAwareOrderProviderTests.java deleted file mode 100644 index 0dd723ca1000..000000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/FactoryAwareOrderProviderTests.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; - -import java.lang.reflect.Method; -import java.util.HashMap; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.core.annotation.Order; -import org.springframework.util.ReflectionUtils; - -/** - * - * @author Stephane Nicoll - */ -public class FactoryAwareOrderProviderTests { - - @Rule - public final TestName name = new TestName(); - - @Mock - private ConfigurableListableBeanFactory beanFactory; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void noBeanName() { - FactoryAwareOrderProvider orderProvider = createOrderProvider(new HashMap()); - assertNull(orderProvider.getOrder(25)); - } - - @Test - public void beanNameNotRegistered() { - HashMap beans = new HashMap<>(); - beans.put(25, "myBean"); - given(beanFactory.containsBeanDefinition("myBean")).willReturn(false); - FactoryAwareOrderProvider orderProvider = createOrderProvider(beans); - assertNull(orderProvider.getOrder(25)); - verify(beanFactory).containsBeanDefinition("myBean"); - } - - - @Test - public void beanNameNoRootBeanDefinition() { - HashMap beans = new HashMap<>(); - beans.put(25, "myBean"); - given(beanFactory.containsBeanDefinition("myBean")).willReturn(true); - given(beanFactory.getMergedBeanDefinition("myBean")).willReturn(mock(BeanDefinition.class)); - FactoryAwareOrderProvider orderProvider = createOrderProvider(beans); - assertNull(orderProvider.getOrder(25)); - verify(beanFactory).containsBeanDefinition("myBean"); - verify(beanFactory).getMergedBeanDefinition("myBean"); - } - - @Test - public void beanNameNoFactory() { - HashMap beans = new HashMap<>(); - beans.put(25, "myBean"); - RootBeanDefinition rbd = mock(RootBeanDefinition.class); - given(rbd.getResolvedFactoryMethod()).willReturn(null); - - given(beanFactory.containsBeanDefinition("myBean")).willReturn(true); - given(beanFactory.getMergedBeanDefinition("myBean")).willReturn(rbd); - FactoryAwareOrderProvider orderProvider = createOrderProvider(beans); - assertNull(orderProvider.getOrder(25)); - verify(beanFactory).containsBeanDefinition("myBean"); - verify(beanFactory).getMergedBeanDefinition("myBean"); - } - - @Test - public void beanNameFactoryNoOrderValue() { - HashMap beans = new HashMap<>(); - beans.put(25, "myBean"); - - Method m = ReflectionUtils.findMethod(getClass(), name.getMethodName()); - RootBeanDefinition rbd = mock(RootBeanDefinition.class); - given(rbd.getResolvedFactoryMethod()).willReturn(m); - - given(beanFactory.containsBeanDefinition("myBean")).willReturn(true); - given(beanFactory.getMergedBeanDefinition("myBean")).willReturn(rbd); - FactoryAwareOrderProvider orderProvider = createOrderProvider(beans); - assertNull(orderProvider.getOrder(25)); - verify(beanFactory).containsBeanDefinition("myBean"); - verify(beanFactory).getMergedBeanDefinition("myBean"); - } - - @Test - @Order(500) - public void beanNameFactoryOrderValue() { - HashMap beans = new HashMap<>(); - beans.put(25, "myBean"); - - Method m = ReflectionUtils.findMethod(getClass(), name.getMethodName()); - RootBeanDefinition rbd = mock(RootBeanDefinition.class); - given(rbd.getResolvedFactoryMethod()).willReturn(m); - - given(beanFactory.containsBeanDefinition("myBean")).willReturn(true); - given(beanFactory.getMergedBeanDefinition("myBean")).willReturn(rbd); - FactoryAwareOrderProvider orderProvider = createOrderProvider(beans); - assertEquals(Integer.valueOf(500), orderProvider.getOrder(25)); - verify(beanFactory).containsBeanDefinition("myBean"); - verify(beanFactory).getMergedBeanDefinition("myBean"); - } - - private FactoryAwareOrderProvider createOrderProvider(HashMap beans) { - return new FactoryAwareOrderProvider(beans, beanFactory); - } - -} diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java index 713ae8d567ad..672134135be1 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java @@ -28,7 +28,6 @@ import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.DefaultDependencyComparator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.GenericApplicationContext; @@ -49,7 +48,6 @@ * @author Juergen Hoeller * @author Chris Beams * @author Phillip Webb - * @author Stephane Nicoll * @since 2.5 * @see ContextAnnotationAutowireCandidateResolver * @see CommonAnnotationBeanPostProcessor @@ -136,7 +134,7 @@ public static Set registerAnnotationConfigProcessors( DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { - beanFactory.setDependencyComparator(DefaultDependencyComparator.INSTANCE); + beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/spr11310/Spr11310Tests.java b/spring-context/src/test/java/org/springframework/context/annotation/Spr11310Tests.java similarity index 97% rename from spring-context/src/test/java/org/springframework/context/annotation/spr11310/Spr11310Tests.java rename to spring-context/src/test/java/org/springframework/context/annotation/Spr11310Tests.java index d4c21d7e322e..a11f7dc70134 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/spr11310/Spr11310Tests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/Spr11310Tests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.context.annotation.spr11310; +package org.springframework.context.annotation; import static org.junit.Assert.*; @@ -30,7 +30,6 @@ import org.springframework.core.annotation.Order; /** - * * @author Stephane Nicoll */ public class Spr11310Tests { diff --git a/spring-core/src/main/java/org/springframework/core/OrderComparator.java b/spring-core/src/main/java/org/springframework/core/OrderComparator.java index 0a261279a756..6308044d96e7 100644 --- a/spring-core/src/main/java/org/springframework/core/OrderComparator.java +++ b/spring-core/src/main/java/org/springframework/core/OrderComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -43,8 +43,27 @@ public class OrderComparator implements Comparator { public static final OrderComparator INSTANCE = new OrderComparator(); + /** + * Build an adapted order comparator with the given soruce provider. + * @param sourceProvider the order source provider to use + * @return the adapted comparator + * @since 4.1 + */ + public Comparator withSourceProvider(final OrderSourceProvider sourceProvider) { + return new Comparator() { + @Override + public int compare(Object o1, Object o2) { + return doCompare(o1, o2, sourceProvider); + } + }; + } + @Override public int compare(Object o1, Object o2) { + return doCompare(o1, o2, null); + } + + private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) { boolean p1 = (o1 instanceof PriorityOrdered); boolean p2 = (o2 instanceof PriorityOrdered); if (p1 && !p2) { @@ -55,20 +74,62 @@ else if (p2 && !p1) { } // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation. - int i1 = getOrder(o1); - int i2 = getOrder(o2); + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0; } /** * Determine the order value for the given object. - *

The default implementation checks against the {@link Ordered} - * interface. Can be overridden in subclasses. + *

The default implementation checks against the given {@link OrderSourceProvider} + * using {@link #findOrder} and falls back to a regular {@link #getOrder(Object)} call. + * @param obj the object to check + * @return the order value, or {@code Ordered.LOWEST_PRECEDENCE} as fallback + */ + private int getOrder(Object obj, OrderSourceProvider sourceProvider) { + Integer order = null; + if (sourceProvider != null) { + order = findOrder(sourceProvider.getOrderSource(obj)); + } + return (order != null ? order : getOrder(obj)); + } + + /** + * Determine the order value for the given object. + *

The default implementation checks against the {@link Ordered} interface + * through delegating to {@link #findOrder}. Can be overridden in subclasses. * @param obj the object to check * @return the order value, or {@code Ordered.LOWEST_PRECEDENCE} as fallback */ protected int getOrder(Object obj) { - return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE); + Integer order = findOrder(obj); + return (order != null ? order : Ordered.LOWEST_PRECEDENCE); + } + + /** + * Find an order value indicated by the given object. + *

The default implementation checks against the {@link Ordered} interface. + * Can be overridden in subclasses. + * @param obj the object to check + * @return the order value, or {@code null} if none found + */ + protected Integer findOrder(Object obj) { + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + + /** + * Determine a priority value for the given object, if any. + *

The default implementation always returns {@code null}. + * Subclasses may override this to give specific kinds of values a + * 'priority' characteristic, in addition to their 'order' semantics. + * A priority indicates that it may be used for selecting one object over + * another, in addition to serving for ordering purposes in a list/array. + * @param obj the object to check + * @return the priority value, or {@code null} if none + * @since 4.1 + */ + public Integer getPriority(Object obj) { + return null; } @@ -115,4 +176,22 @@ else if (value instanceof List) { } } + + /** + * Strategy interface to provide an order source for a given object. + * @since 4.1 + */ + public static interface OrderSourceProvider { + + /** + * Return an order source for the specified object, i.e. an object that + * should be checked for an order value as a replacement to the given object. + *

If the returned object does not indicate any order, the comparator + * will fall back to checking the original object. + * @param obj the object to find an order source for + * @return the order source for that object, or {@code null} if none found + */ + Object getOrderSource(Object obj); + } + } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java index 760bdf5119da..13d2382b97b4 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java @@ -16,19 +16,20 @@ package org.springframework.core.annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.springframework.core.OrderComparator; -import org.springframework.core.Ordered; /** - * {@link java.util.Comparator} implementation that checks - * {@link org.springframework.core.Ordered} as well as the - * {@link Order} annotation, with an order value provided by an - * {@code Ordered} instance overriding a statically defined - * annotation value (if any). + * {@link java.util.Comparator} implementation that checks Spring's + * {@link org.springframework.core.Ordered} interface as well as the + * {@link Order} annotation and the {@link javax.annotation.Priority} + * annotation, with an order value provided by an {@code Ordered} + * instance overriding a statically defined annotation value (if any). * * @author Juergen Hoeller * @author Oliver Gierke @@ -36,6 +37,7 @@ * @since 2.0.1 * @see org.springframework.core.Ordered * @see Order + * @see javax.annotation.Priority */ public class AnnotationAwareOrderComparator extends OrderComparator { @@ -45,16 +47,55 @@ public class AnnotationAwareOrderComparator extends OrderComparator { public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); - @Override - protected int getOrder(Object obj) { - if (obj instanceof Ordered) { - return ((Ordered) obj).getOrder(); + /** + * This implementation checks for the {@link Order} annotation + * on various kinds of elements, in addition to the + * {@link org.springframework.core.Ordered} check in the superclass. + */ + protected Integer findOrder(Object obj) { + // Check for regular Ordered interface + Integer order = super.findOrder(obj); + if (order != null) { + return order; + } + + // Check for @Order annotation on various kinds of elements + if (obj instanceof Class) { + return OrderUtils.getOrder((Class) obj); + } + else if (obj instanceof Method) { + Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class); + if (ann != null) { + return ann.value(); + } + } + else if (obj instanceof AnnotatedElement) { + Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class); + if (ann != null) { + return ann.value(); + } + } + else if (obj != null) { + return OrderUtils.getOrder(obj.getClass()); + } + + return null; + } + + /** + * This implementation checks retrieves a {@link javax.annotation.Priority} + * value, allowing for additional semantics over the regular {@link Order} + * annotation: typically, selecting one object over another in case of + * multiple matches but only one object to be returned. + */ + public Integer getPriority(Object obj) { + if (obj instanceof Class) { + return OrderUtils.getPriority((Class) obj); } - if (obj != null) { - Class clazz = (obj instanceof Class ? (Class) obj : obj.getClass()); - return OrderUtils.getOrder(clazz, Ordered.LOWEST_PRECEDENCE); + else if (obj != null) { + return OrderUtils.getPriority(obj.getClass()); } - return Ordered.LOWEST_PRECEDENCE; + return null; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/DefaultOrderProviderComparator.java b/spring-core/src/main/java/org/springframework/core/annotation/DefaultOrderProviderComparator.java deleted file mode 100644 index b99e089c4cdc..000000000000 --- a/spring-core/src/main/java/org/springframework/core/annotation/DefaultOrderProviderComparator.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core.annotation; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * A default {@link OrderProviderComparator} implementation that uses the - * value provided by the {@link OrderProvider} and fallbacks to - * {@link AnnotationAwareOrderComparator} if none is set. - * - *

This essentially means that the value of the {@link OrderProvider} - * takes precedence over the behavior of {@link AnnotationAwareOrderComparator} - * - * @author Stephane Nicoll - * @since 4.1 - */ -public class DefaultOrderProviderComparator implements OrderProviderComparator { - - /** - * Shared default instance of DefaultOrderProviderComparator. - */ - public static final DefaultOrderProviderComparator INSTANCE = new DefaultOrderProviderComparator(); - - - @Override - public void sortList(List items, OrderProvider orderProvider) { - Collections.sort(items, new OrderProviderAwareComparator(orderProvider)); - } - - @Override - public void sortArray(Object[] items, OrderProvider orderProvider) { - Arrays.sort(items, new OrderProviderAwareComparator(orderProvider)); - } - - - private static class OrderProviderAwareComparator extends AnnotationAwareOrderComparator { - - private final OrderProvider orderProvider; - - public OrderProviderAwareComparator(OrderProvider orderProvider) { - this.orderProvider = orderProvider; - } - - @Override - protected int getOrder(Object obj) { - Integer order = this.orderProvider.getOrder(obj); - if (order != null) { - return order; - } - return super.getOrder(obj); - } - } - -} diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderProvider.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderProvider.java deleted file mode 100644 index 58c9e05ab530..000000000000 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core.annotation; - -/** - * Strategy interface to provide the order value of a given instance. - * - * @author Stephane Nicoll - * @since 4.1 - * @see OrderProviderComparator - */ -public interface OrderProvider { - - /** - * Return the order value of the specified object or {@code null} if - * it cannot be retrieved. - * @param obj the object to handle - * @return the order value for that object or {@code null} if none is found - */ - Integer getOrder(Object obj); - -} diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderProviderComparator.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderProviderComparator.java deleted file mode 100644 index 37c8394f4bfd..000000000000 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderProviderComparator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2002-2014 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core.annotation; - -import java.util.List; - -/** - * Sort a collection of element according to an {@link OrderProvider}. - * - * @author Stephane Nicoll - * @since 4.1 - */ -public interface OrderProviderComparator { - - /** - * Sort the specified list of items according to their order value, - * using the specified {@link OrderProvider} to retrieve an order - * if necessary. - * @param items the items to sort - * @param orderProvider the order provider to use - * @see java.util.Collections#sort(java.util.List, java.util.Comparator) - */ - void sortList(List items, OrderProvider orderProvider); - - /** - * Sort the specified array of items according to their order value, - * using the specified {@link OrderProvider} to retrieve an order - * if necessary. - * @param items the items to sort - * @param orderProvider the order provider to use - * @see java.util.Arrays#sort(Object[], java.util.Comparator) - */ - void sortArray(Object[] items, OrderProvider orderProvider); - -} diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java index 849b7c1c642a..c3ac8dfcf1fb 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java @@ -38,7 +38,17 @@ public abstract class OrderUtils { /** - * Return the order on the specified {@code type} or the specified + * Return the order on the specified {@code type}. + *

Take care of {@link Order @Order} and {@code @javax.annotation.Priority}. + * @param type the type to handle + * @return the order value, or {@code null} if none can be found + */ + public static Integer getOrder(Class type) { + return getOrder(type, null); + } + + /** + * Return the order on the specified {@code type}, or the specified * default value if none can be found. *

Take care of {@link Order @Order} and {@code @javax.annotation.Priority}. * @param type the type to handle @@ -49,7 +59,7 @@ public static Integer getOrder(Class type, Integer defaultOrder) { if (order != null) { return order.value(); } - Integer priorityOrder = getPriorityValue(type); + Integer priorityOrder = getPriority(type); if (priorityOrder != null) { return priorityOrder; } @@ -62,7 +72,7 @@ public static Integer getOrder(Class type, Integer defaultOrder) { * @param type the type to handle * @return the priority value if the annotation is set, {@code null} otherwise */ - public static Integer getPriorityValue(Class type) { + public static Integer getPriority(Class type) { if (priorityPresent) { for (Annotation annotation : type.getAnnotations()) { if (PRIORITY_ANNOTATION_CLASS_NAME.equals(annotation.annotationType().getName())) { diff --git a/spring-core/src/test/java/org/springframework/core/annotation/DefaultOrderProviderComparatorTests.java b/spring-core/src/test/java/org/springframework/core/annotation/OrderSourceProviderTests.java similarity index 69% rename from spring-core/src/test/java/org/springframework/core/annotation/DefaultOrderProviderComparatorTests.java rename to spring-core/src/test/java/org/springframework/core/annotation/OrderSourceProviderTests.java index 950de24126cb..463e3b6ef7d4 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/DefaultOrderProviderComparatorTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/OrderSourceProviderTests.java @@ -16,22 +16,36 @@ package org.springframework.core.annotation; -import static org.junit.Assert.*; - +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Test; import org.springframework.core.Ordered; +import static org.junit.Assert.*; + /** - * * @author Stephane Nicoll + * @author Juergen Hoeller */ -public class DefaultOrderProviderComparatorTests { +public class OrderSourceProviderTests { + + private final AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE; - private final DefaultOrderProviderComparator comparator = new DefaultOrderProviderComparator(); + + @Test + public void plainComparator() { + List items = new ArrayList(); + C c = new C(5); + C c2 = new C(-5); + items.add(c); + items.add(c2); + Collections.sort(items, comparator); + assertOrder(items, c2, c); + } @Test public void listNoFactoryMethod() { @@ -40,12 +54,7 @@ public void listNoFactoryMethod() { B b = new B(); List items = Arrays.asList(a, c, b); - comparator.sortList(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - return null; - } - }); + Collections.sort(items, comparator.withSourceProvider(obj -> null)); assertOrder(items, c, a, b); } @@ -56,18 +65,15 @@ public void listFactoryMethod() { B b = new B(); List items = Arrays.asList(a, c, b); - comparator.sortList(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - if (obj == a) { - return 4; - } - if (obj == b) { - return 2; - } - return null; + Collections.sort(items, comparator.withSourceProvider(obj -> { + if (obj == a) { + return new C(4); + } + if (obj == b) { + return new C(2); } - }); + return null; + })); assertOrder(items, b, c, a); } @@ -77,20 +83,16 @@ public void listFactoryMethodOverridesStaticOrder() { C c = new C(5); C c2 = new C(-5); - List items = Arrays.asList(a, c, c2); - comparator.sortList(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - if (obj == a) { - return 4; - } - if (obj == c2) { - return 2; - } - return null; + Collections.sort(items, comparator.withSourceProvider(obj -> { + if (obj == a) { + return 4; } - }); + if (obj == c2) { + return 2; + } + return null; + })); assertOrder(items, c2, a, c); } @@ -101,12 +103,7 @@ public void arrayNoFactoryMethod() { B b = new B(); Object[] items = new Object[] {a, c, b}; - comparator.sortArray(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - return null; - } - }); + Arrays.sort(items, comparator.withSourceProvider(obj -> null)); assertOrder(items, c, a, b); } @@ -117,18 +114,15 @@ public void arrayFactoryMethod() { B b = new B(); Object[] items = new Object[] {a, c, b}; - comparator.sortArray(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - if (obj == a) { - return 4; - } - if (obj == b) { - return 2; - } - return null; + Arrays.sort(items, comparator.withSourceProvider(obj -> { + if (obj == a) { + return new C(4); + } + if (obj == b) { + return new C(2); } - }); + return null; + })); assertOrder(items, b, c, a); } @@ -139,21 +133,19 @@ public void arrayFactoryMethodOverridesStaticOrder() { C c2 = new C(-5); Object[] items = new Object[] {a, c, c2}; - comparator.sortArray(items, new OrderProvider() { - @Override - public Integer getOrder(Object obj) { - if (obj == a) { - return 4; - } - if (obj == c2) { - return 2; - } - return null; + Arrays.sort(items, comparator.withSourceProvider(obj -> { + if (obj == a) { + return 4; } - }); + if (obj == c2) { + return 2; + } + return null; + })); assertOrder(items, c2, a, c); } + private void assertOrder(List actual, Object... expected) { for (int i = 0; i < actual.size(); i++) { assertSame("Wrong instance at index '" + i + "'", expected[i], actual.get(i)); @@ -173,11 +165,14 @@ private void assertOrder(Object[] actual, Object... expected) { private static class A { } + @Order(2) private static class B { } + private static class C implements Ordered { + private final int order; private C(int order) { diff --git a/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java index c4968db59cde..8ac1dd95a563 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java @@ -50,12 +50,12 @@ public void getDefaultOrder() { @Test public void getPriorityValueNoAnnotation() { - assertNull(OrderUtils.getPriorityValue(SimpleOrder.class)); + assertNull(OrderUtils.getPriority(SimpleOrder.class)); } @Test public void getPriorityValue() { - assertEquals(Integer.valueOf(55), OrderUtils.getPriorityValue(OrderAndPriority.class)); + assertEquals(Integer.valueOf(55), OrderUtils.getPriority(OrderAndPriority.class)); } @Order(50)