Detect Order on target class as well
Previously, the `@Order` annotation was managed in an inconsistent way when placed at the implementation level. For simple beans, it was discovered properly but wasn't for beans requiring a proxy. OrderComparator.SourceProvider now explicitly allows to return several order sources; the default implementation returns not only the factory method (if any) but also the target class if it happens to be different from the class of the bean. Issue: SPR-12636
This commit is contained in:
@@ -21,6 +21,8 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link Comparator} implementation for {@link Ordered} objects,
|
||||
* sorting by order value ascending (resp. by priority descending).
|
||||
@@ -89,7 +91,19 @@ public class OrderComparator implements Comparator<Object> {
|
||||
private int getOrder(Object obj, OrderSourceProvider sourceProvider) {
|
||||
Integer order = null;
|
||||
if (sourceProvider != null) {
|
||||
order = findOrder(sourceProvider.getOrderSource(obj));
|
||||
Object orderSource = sourceProvider.getOrderSource(obj);
|
||||
if (orderSource != null && orderSource.getClass().isArray()) {
|
||||
Object[] sources = ObjectUtils.toObjectArray(orderSource);
|
||||
for (Object source : sources) {
|
||||
order = findOrder(source);
|
||||
if (order != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
order = findOrder(orderSource);
|
||||
}
|
||||
}
|
||||
return (order != null ? order : getOrder(obj));
|
||||
}
|
||||
@@ -186,6 +200,7 @@ public class OrderComparator implements Comparator<Object> {
|
||||
/**
|
||||
* 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.
|
||||
* <p>Can also be an array of order source objects.
|
||||
* <p>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
|
||||
|
||||
@@ -18,43 +18,90 @@ package org.springframework.core;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link OrderComparator} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public final class OrderComparatorTests extends TestCase {
|
||||
public final class OrderComparatorTests {
|
||||
|
||||
private Comparator comparator;
|
||||
private final OrderComparator comparator = new OrderComparator();
|
||||
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
this.comparator = new OrderComparator();
|
||||
}
|
||||
|
||||
|
||||
public void testCompareOrderedInstancesBefore() throws Exception {
|
||||
@Test
|
||||
public void compareOrderedInstancesBefore() {
|
||||
assertEquals(-1, this.comparator.compare(
|
||||
new StubOrdered(100), new StubOrdered(2000)));
|
||||
}
|
||||
|
||||
public void testCompareOrderedInstancesSame() throws Exception {
|
||||
@Test
|
||||
public void compareOrderedInstancesSame() {
|
||||
assertEquals(0, this.comparator.compare(
|
||||
new StubOrdered(100), new StubOrdered(100)));
|
||||
}
|
||||
|
||||
public void testCompareOrderedInstancesAfter() throws Exception {
|
||||
@Test
|
||||
public void compareOrderedInstancesAfter() {
|
||||
assertEquals(1, this.comparator.compare(
|
||||
new StubOrdered(982300), new StubOrdered(100)));
|
||||
}
|
||||
|
||||
public void testCompareTwoNonOrderedInstancesEndsUpAsSame() throws Exception {
|
||||
@Test
|
||||
public void compareTwoNonOrderedInstancesEndsUpAsSame() {
|
||||
assertEquals(0, this.comparator.compare(new Object(), new Object()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareWithSimpleSourceProvider() {
|
||||
Comparator<Object> customComparator = this.comparator.withSourceProvider(
|
||||
new TestSourceProvider(5L, new StubOrdered(25)));
|
||||
assertEquals(-1, customComparator.compare(new StubOrdered(10), 5L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareWithSourceProviderArray() {
|
||||
Comparator<Object> customComparator = this.comparator.withSourceProvider(
|
||||
new TestSourceProvider(5L, new Object[] {new StubOrdered(10), new StubOrdered(-25)}));
|
||||
assertEquals(-1, customComparator.compare(5L, new Object()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareWithSourceProviderArrayNoMatch() {
|
||||
Comparator<Object> customComparator = this.comparator.withSourceProvider(
|
||||
new TestSourceProvider(5L, new Object[]{new Object(), new Object()}));
|
||||
assertEquals(0, customComparator.compare(new Object(), 5L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareWithSourceProviderEmpty() {
|
||||
Comparator<Object> customComparator = this.comparator.withSourceProvider(
|
||||
new TestSourceProvider(50L, new Object()));
|
||||
assertEquals(0, customComparator.compare(new Object(), 5L));
|
||||
}
|
||||
|
||||
|
||||
private static final class TestSourceProvider implements OrderComparator.OrderSourceProvider {
|
||||
|
||||
private final Object target;
|
||||
private final Object orderSource;
|
||||
|
||||
public TestSourceProvider(Object target, Object orderSource) {
|
||||
this.target = target;
|
||||
this.orderSource = orderSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrderSource(Object obj) {
|
||||
if (target.equals(obj)) {
|
||||
return orderSource;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StubOrdered implements Ordered {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user