Skip to content

Commit 68d9e5d

Browse files
committed
Merge branch '6.1.x'
2 parents 23f19a0 + d72c8b3 commit 68d9e5d

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,12 +1996,15 @@ else if (candidateLocal) {
19961996
* @param requiredType the target dependency type to match against
19971997
* @return the name of the candidate with the highest priority,
19981998
* or {@code null} if none found
1999+
* @throws NoUniqueBeanDefinitionException if multiple beans are detected with
2000+
* the same highest priority value
19992001
* @see #getPriority(Object)
20002002
*/
20012003
@Nullable
20022004
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
20032005
String highestPriorityBeanName = null;
20042006
Integer highestPriority = null;
2007+
boolean highestPriorityConflictDetected = false;
20052008
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
20062009
String candidateBeanName = entry.getKey();
20072010
Object beanInstance = entry.getValue();
@@ -2010,13 +2013,12 @@ protected String determineHighestPriorityCandidate(Map<String, Object> candidate
20102013
if (candidatePriority != null) {
20112014
if (highestPriority != null) {
20122015
if (candidatePriority.equals(highestPriority)) {
2013-
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
2014-
"Multiple beans found with the same priority ('" + highestPriority +
2015-
"') among candidates: " + candidates.keySet());
2016+
highestPriorityConflictDetected = true;
20162017
}
20172018
else if (candidatePriority < highestPriority) {
20182019
highestPriorityBeanName = candidateBeanName;
20192020
highestPriority = candidatePriority;
2021+
highestPriorityConflictDetected = false;
20202022
}
20212023
}
20222024
else {
@@ -2026,6 +2028,13 @@ else if (candidatePriority < highestPriority) {
20262028
}
20272029
}
20282030
}
2031+
2032+
if (highestPriorityConflictDetected) {
2033+
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
2034+
"Multiple beans found with the same highest priority (" + highestPriority +
2035+
") among candidates: " + candidates.keySet());
2036+
2037+
}
20292038
return highestPriorityBeanName;
20302039
}
20312040

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

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,18 +1718,73 @@ void mapInjectionWithPriority() {
17181718
assertThat(bean.getBeanName()).isEqualTo("bd1");
17191719
}
17201720

1721+
/**
1722+
* {@code determineHighestPriorityCandidate()} should reject duplicate
1723+
* priorities for the highest priority detected.
1724+
*
1725+
* @see #getBeanByTypeWithMultipleNonHighestPriorityCandidates()
1726+
*/
17211727
@Test
1722-
void getBeanByTypeWithMultiplePriority() {
1728+
void getBeanByTypeWithMultipleHighestPriorityCandidates() {
17231729
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
17241730
RootBeanDefinition bd1 = new RootBeanDefinition(HighPriorityTestBean.class);
1725-
RootBeanDefinition bd2 = new RootBeanDefinition(HighPriorityTestBean.class);
1731+
RootBeanDefinition bd2 = new RootBeanDefinition(LowPriorityTestBean.class);
1732+
RootBeanDefinition bd3 = new RootBeanDefinition(HighPriorityTestBean.class);
17261733
lbf.registerBeanDefinition("bd1", bd1);
17271734
lbf.registerBeanDefinition("bd2", bd2);
1735+
lbf.registerBeanDefinition("bd3", bd3);
17281736

17291737
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class)
17301738
.isThrownBy(() -> lbf.getBean(TestBean.class))
1731-
.withMessageContaining("Multiple beans found with the same priority")
1732-
.withMessageContaining("5"); // conflicting priority
1739+
.withMessageContaining("Multiple beans found with the same highest priority (5) among candidates: ");
1740+
}
1741+
1742+
/**
1743+
* {@code determineHighestPriorityCandidate()} should ignore duplicate
1744+
* priorities for any priority other than the highest, and the order in
1745+
* which beans is declared should not affect the outcome.
1746+
*
1747+
* @see #getBeanByTypeWithMultipleHighestPriorityCandidates()
1748+
*/
1749+
@Test // gh-33733
1750+
void getBeanByTypeWithMultipleNonHighestPriorityCandidates() {
1751+
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
1752+
PriorityService1.class,
1753+
PriorityService2A.class,
1754+
PriorityService2B.class,
1755+
PriorityService3.class
1756+
);
1757+
1758+
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
1759+
PriorityService3.class,
1760+
PriorityService2B.class,
1761+
PriorityService2A.class,
1762+
PriorityService1.class
1763+
);
1764+
1765+
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
1766+
PriorityService2A.class,
1767+
PriorityService1.class,
1768+
PriorityService2B.class,
1769+
PriorityService3.class
1770+
);
1771+
1772+
getBeanByTypeWithMultipleNonHighestPriorityCandidates(
1773+
PriorityService2A.class,
1774+
PriorityService3.class,
1775+
PriorityService1.class,
1776+
PriorityService2B.class
1777+
);
1778+
}
1779+
1780+
private void getBeanByTypeWithMultipleNonHighestPriorityCandidates(Class<?>... classes) {
1781+
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
1782+
for (Class<?> clazz : classes) {
1783+
lbf.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
1784+
}
1785+
1786+
PriorityService bean = lbf.getBean(PriorityService.class);
1787+
assertThat(bean).isExactlyInstanceOf(PriorityService1.class);
17331788
}
17341789

17351790
@Test
@@ -3519,6 +3574,26 @@ public KnowsIfInstantiated() {
35193574
}
35203575

35213576

3577+
interface PriorityService {
3578+
}
3579+
3580+
@Priority(1)
3581+
static class PriorityService1 implements PriorityService {
3582+
}
3583+
3584+
@Priority(2)
3585+
static class PriorityService2A implements PriorityService {
3586+
}
3587+
3588+
@Priority(2)
3589+
static class PriorityService2B implements PriorityService {
3590+
}
3591+
3592+
@Priority(3)
3593+
static class PriorityService3 implements PriorityService {
3594+
}
3595+
3596+
35223597
@Priority(5)
35233598
private static class HighPriorityTestBean extends TestBean {
35243599
}

0 commit comments

Comments
 (0)