Browse Source

Merge branch '6.1.x'

pull/33697/head
Sam Brannen 1 year ago
parent
commit
68d9e5d81a
  1. 15
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  2. 83
      spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

15
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

@ -1996,12 +1996,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1996,12 +1996,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority,
* or {@code null} if none found
* @throws NoUniqueBeanDefinitionException if multiple beans are detected with
* the same highest priority value
* @see #getPriority(Object)
*/
@Nullable
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
boolean highestPriorityConflictDetected = false;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
@ -2010,13 +2013,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -2010,13 +2013,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (candidatePriority != null) {
if (highestPriority != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
highestPriorityConflictDetected = true;
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
highestPriorityConflictDetected = false;
}
}
else {
@ -2026,6 +2028,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -2026,6 +2028,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
}
if (highestPriorityConflictDetected) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same highest priority (" + highestPriority +
") among candidates: " + candidates.keySet());
}
return highestPriorityBeanName;
}

83
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

@ -1718,18 +1718,73 @@ class DefaultListableBeanFactoryTests { @@ -1718,18 +1718,73 @@ class DefaultListableBeanFactoryTests {
assertThat(bean.getBeanName()).isEqualTo("bd1");
}
/**
* {@code determineHighestPriorityCandidate()} should reject duplicate
* priorities for the highest priority detected.
*
* @see #getBeanByTypeWithMultipleNonHighestPriorityCandidates()
*/
@Test
void getBeanByTypeWithMultiplePriority() {
void getBeanByTypeWithMultipleHighestPriorityCandidates() {
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class);
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class);
RootBeanDefinition bd3 = new RootBeanDefinition(HighPriorityTestBean.class);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
lbf.registerBeanDefinition("bd3", bd3);
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class)
.isThrownBy(() -> lbf.getBean(TestBean.class))
.withMessageContaining("Multiple beans found with the same priority")
.withMessageContaining("5"); // conflicting priority
.withMessageContaining("Multiple beans found with the same highest priority (5) among candidates: ");
}
/**
* {@code determineHighestPriorityCandidate()} should ignore duplicate
* priorities for any priority other than the highest, and the order in
* which beans is declared should not affect the outcome.
*
* @see #getBeanByTypeWithMultipleHighestPriorityCandidates()
*/
@Test // gh-33733
void getBeanByTypeWithMultipleNonHighestPriorityCandidates() {
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
PriorityService1.class,
PriorityService2A.class,
PriorityService2B.class,
PriorityService3.class
);
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
PriorityService3.class,
PriorityService2B.class,
PriorityService2A.class,
PriorityService1.class
);
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
PriorityService2A.class,
PriorityService1.class,
PriorityService2B.class,
PriorityService3.class
);
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
PriorityService2A.class,
PriorityService3.class,
PriorityService1.class,
PriorityService2B.class
);
}
private void getBeanByTypeWithMultipleNonHighestPriorityCandidates(Class<?>... classes) {
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
for (Class<?> clazz : classes) {
lbf.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
}
PriorityService bean = lbf.getBean(PriorityService.class);
assertThat(bean).isExactlyInstanceOf(PriorityService1.class);
}
@Test
@ -3519,6 +3574,26 @@ class DefaultListableBeanFactoryTests { @@ -3519,6 +3574,26 @@ class DefaultListableBeanFactoryTests {
}
interface PriorityService {
}
@Priority(1)
static class PriorityService1 implements PriorityService {
}
@Priority(2)
static class PriorityService2A implements PriorityService {
}
@Priority(2)
static class PriorityService2B implements PriorityService {
}
@Priority(3)
static class PriorityService3 implements PriorityService {
}
@Priority(5)
private static class HighPriorityTestBean extends TestBean {
}

Loading…
Cancel
Save