Skip to content

Commit

Permalink
Refactored support for @order on @bean methods as well as @priority h…
Browse files Browse the repository at this point in the history
…andling

Issue: SPR-11310
Issue: SPR-10548
  • Loading branch information
jhoeller committed Sep 3, 2014
1 parent 82f8b43 commit c6d29f1
Show file tree
Hide file tree
Showing 17 changed files with 281 additions and 661 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -1029,32 +1029,22 @@ else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
}
}

private void sortArray(Object[] items, Map<String, Object> matchingBeans) {
if (this.dependencyComparator instanceof OrderProviderComparator) {
((OrderProviderComparator) this.dependencyComparator)
.sortArray(items, createFactoryAwareOrderProvider(matchingBeans));
private Comparator<Object> adaptDependencyComparator(Map<String, Object> 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<String, Object> matchingBeans) {
if (this.dependencyComparator instanceof OrderProviderComparator) {
((OrderProviderComparator) this.dependencyComparator)
.sortList(items, createFactoryAwareOrderProvider(matchingBeans));
}
else {
Collections.sort(items, this.dependencyComparator);
}
}

private FactoryAwareOrderProvider createFactoryAwareOrderProvider(Map<String, Object> beans) {
private FactoryAwareOrderSourceProvider createFactoryAwareOrderSourceProvider(Map<String, Object> beans) {
IdentityHashMap<Object, String> instancesToBeanNames = new IdentityHashMap<Object, String>();
for (Map.Entry<String, Object> entry : beans.entrySet()) {
instancesToBeanNames.put(entry.getValue(), entry.getKey());
}
return new FactoryAwareOrderProvider(instancesToBeanNames, this);
return new FactoryAwareOrderSourceProvider(instancesToBeanNames);
}

/**
Expand Down Expand Up @@ -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.
* <p>If the annotation is not present, returns {@code null}.
* @param beanInstance the bean instance to check (can be null)
* <p>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;
}
Expand Down Expand Up @@ -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.
* <p>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<Object, String> instancesToBeanNames;

public FactoryAwareOrderSourceProvider(Map<Object, String> 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;
}
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
Loading

0 comments on commit c6d29f1

Please sign in to comment.