Skip to content

Throw Exception when two primary beans are present in one factory #26612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1647,28 +1647,36 @@ protected String determineAutowireCandidate(Map<String, Object> candidates, Depe
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the primary candidate, or {@code null} if none found
* @see #isPrimary(String, Object)
*/
@Nullable
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
DefaultListableBeanFactory primaryBeanFactory = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
DefaultListableBeanFactory beanFactory = this;
boolean isPrimary = false;
while (beanFactory != primaryBeanFactory) {
String transformedCandidateBeanName = beanFactory.transformedBeanName(candidateBeanName);
if (beanFactory.containsBeanDefinition(transformedCandidateBeanName)) {
isPrimary = beanFactory.getMergedLocalBeanDefinition(transformedCandidateBeanName).isPrimary();
break;
}
else {
primaryBeanName = candidateBeanName;
BeanFactory parent = beanFactory.getParentBeanFactory();
beanFactory = parent instanceof DefaultListableBeanFactory ? (DefaultListableBeanFactory) parent : null;
}
}
if (isPrimary) {
primaryBeanName = candidateBeanName;
primaryBeanFactory = beanFactory;
}
else if (beanFactory == primaryBeanFactory && null != beanFactory){
String transformedCandidateBeanName = beanFactory.transformedBeanName(candidateBeanName);
if(beanFactory.containsBeanDefinition(transformedCandidateBeanName) &&
beanFactory.getMergedLocalBeanDefinition(transformedCandidateBeanName).isPrimary()) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1979,6 +1979,35 @@ void autowireBeanByTypeWithTwoPrimaryCandidates() {
.withCauseExactlyInstanceOf(NoUniqueBeanDefinitionException.class);
}

@Test
void autowireBeanByTypeWithTwoPrimaryCandidatesInOneAncestor() {
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPrimary(true);
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
bd2.setPrimary(true);
parent.registerBeanDefinition("test", bd);
parent.registerBeanDefinition("spouse", bd2);
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(parent);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true))
.withCauseExactlyInstanceOf(NoUniqueBeanDefinitionException.class);
}

@Test
void autowireBeanByTypeWithTwoPrimaryFactoryBeans(){
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
RootBeanDefinition bd1 = new RootBeanDefinition(LazyInitFactory.class);
RootBeanDefinition bd2 = new RootBeanDefinition(LazyInitFactory.class);
bd1.setPrimary(true);
bd2.setPrimary(true);
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", bd2);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(() ->
lbf.autowire(FactoryBeanDependentBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true))
.withCauseExactlyInstanceOf(NoUniqueBeanDefinitionException.class);
}

@Test
void autowireBeanByTypeWithTwoMatchesAndPriority() {
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
Expand Down