Add support for @Priority
This commit adds support for @Priority to filter multiple candidates for autowiring. When multiple candidates are available for a given bean, the bean annotated with @Primary is used. If none exists, the one with the higher value for the @Priority annotation is used. If two beans have the same priority a NoUniqueBeanDefinitionException is thrown, just as if two beans are annotated with @Primary. The underlying code for #getBean and #resolveDependency has been merged as this feature is available for both dependency injection and bean lookup by type. Issue: SPR-10548
This commit is contained in:
@@ -32,6 +32,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Priority;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -99,6 +100,7 @@ import static org.mockito.BDDMockito.*;
|
||||
* @author Sam Brannen
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class DefaultListableBeanFactoryTests {
|
||||
|
||||
@@ -1377,6 +1379,42 @@ public class DefaultListableBeanFactoryTests {
|
||||
lbf.getBean(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeWithPriority() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeWithMultiplePriority() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
thrown.expect(NoUniqueBeanDefinitionException.class);
|
||||
thrown.expectMessage(containsString("Multiple beans found with the same priority"));
|
||||
thrown.expectMessage(containsString("500")); // conflicting priority
|
||||
lbf.getBean(TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypePrimaryHasPrecedenceOverPriority() throws Exception {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setPrimary(true);
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
TestBean bean = lbf.getBean(TestBean.class);
|
||||
assertThat(bean.getBeanName(), equalTo("bd2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeFiltersOutNonAutowireCandidates() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
@@ -1546,6 +1584,53 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatchesAndPriority() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
assertThat(bean.getSpouse(), equalTo(lbf.getBean("test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithIdenticalPriorityCandidates() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertNotNull("Exception should have cause", ex.getCause());
|
||||
assertEquals("Wrong cause type", NoUniqueBeanDefinitionException.class, ex.getCause().getClass());
|
||||
assertTrue(ex.getMessage().contains("500")); // conflicting priority
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypePrimaryTakesPrecedenceOverPriority() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(HighPriorityTestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setPrimary(true);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
assertThat(bean.getSpouse(), equalTo(lbf.getBean("spouse")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireExistingBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
@@ -2802,4 +2887,11 @@ public class DefaultListableBeanFactoryTests {
|
||||
|
||||
}
|
||||
|
||||
@Priority(500)
|
||||
private static class HighPriorityTestBean extends TestBean {}
|
||||
|
||||
@Priority(5)
|
||||
private static class LowPriorityTestBean extends TestBean {}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user