Skip to content

Commit e33ac71

Browse files
committed
Treat the only one default candidate as effectively primary
Close spring-projectsGH-34432 Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
1 parent 21604d1 commit e33ac71

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

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

+32
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
* @author Phillip Webb
119119
* @author Stephane Nicoll
120120
* @author Sebastien Deleuze
121+
* @author Yanming Zhou
121122
* @since 16 April 2001
122123
* @see #registerBeanDefinition
123124
* @see #addBeanPostProcessor
@@ -1479,6 +1480,9 @@ else if (candidateNames.length > 1) {
14791480
if (candidateName == null) {
14801481
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
14811482
}
1483+
if (candidateName == null) {
1484+
candidateName = determineEffectivelyPrimaryCandidate(candidates, requiredType.toClass());
1485+
}
14821486
if (candidateName != null) {
14831487
Object beanInstance = candidates.get(candidateName);
14841488
if (beanInstance == null) {
@@ -2046,6 +2050,34 @@ else if (candidatePriority < highestPriority) {
20462050
return highestPriorityBeanName;
20472051
}
20482052

2053+
/**
2054+
* Determine the candidate which is the only one default candidate in the given set of beans.
2055+
* @param candidates a Map of candidate names and candidate instances
2056+
* (or candidate classes if not created yet) that match the required type
2057+
* @param requiredType the target dependency type to match against
2058+
* @return the name of the only one default candidate,
2059+
* or {@code null} if none found
2060+
*/
2061+
@Nullable
2062+
protected String determineEffectivelyPrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
2063+
String candidateBeanName = null;
2064+
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
2065+
String transformedBeanName = transformedBeanName(entry.getKey());
2066+
if (containsBeanDefinition(transformedBeanName)) {
2067+
RootBeanDefinition bd = getMergedLocalBeanDefinition(transformedBeanName);
2068+
if (bd.isAutowireCandidate() && bd.isDefaultCandidate()) {
2069+
if (candidateBeanName == null) {
2070+
candidateBeanName = entry.getKey();
2071+
}
2072+
else {
2073+
return null;
2074+
}
2075+
}
2076+
}
2077+
}
2078+
return candidateBeanName;
2079+
}
2080+
20492081
/**
20502082
* Return whether the bean definition for the given bean name has been
20512083
* marked as a primary bean.

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

+13
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
* @author Chris Beams
114114
* @author Phillip Webb
115115
* @author Stephane Nicoll
116+
* @author Yanming Zhou
116117
*/
117118
class DefaultListableBeanFactoryTests {
118119

@@ -1664,6 +1665,18 @@ void getBeanByTypeWithPrimary() {
16641665
assertThat(lbf.containsSingleton("bd1")).isFalse();
16651666
}
16661667

1668+
@Test
1669+
void getBeanByTypeWithEffectivelyPrimary() {
1670+
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
1671+
bd1.setDefaultCandidate(false);
1672+
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
1673+
lbf.registerBeanDefinition("bd1", bd1);
1674+
lbf.registerBeanDefinition("bd2", bd2);
1675+
1676+
TestBean bean = lbf.getBean(TestBean.class);
1677+
assertThat(bean.getBeanName()).isEqualTo("bd2");
1678+
}
1679+
16671680
@Test
16681681
@SuppressWarnings("rawtypes")
16691682
void getFactoryBeanByTypeWithPrimary() {

0 commit comments

Comments
 (0)