-
Couldn't load subscription status.
- Fork 38.8k
Description
Overview
When I was reading the source code for DefaultListableBeanFactory#determineHighestPriorityCandidate(), I found that when multiple beans have the same priority but not the highest priority, the highest priority bean cannot be obtained correctly.
Example
Consider the following scenario:
public interface IFacade {
}
@Priority(10)
@Service
public class Facade0 implements IFacade{
}
@Priority(9)
@Service
public class Facade1 implements IFacade{
}
@Priority(9)
@Service
public class Facade2 implements IFacade{
}
@Priority(8)
@Service
public class Facade3 implements IFacade{
}
@Component
public class Config {
@Autowired
private IFacade facade;
}Proposal
I know that @Qualifier or @Primary can be used to handle this situation, but in this case, the highest priority bean is only Facade3, which should be correctly injected into Config instead of throwing an exception.
Can you consider adding the highest priority results to a List (refer to the code below) and throwing an exception if there are multiple beans with the highest priority?
@Nullable
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
List<String> highestPriorityBeanNames = new ArrayList<>();
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (!highestPriorityBeanNames.isEmpty()) {
if (candidatePriority.equals(highestPriority)) {
highestPriorityBeanNames.add(candidateBeanName);
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanNames.clear();
highestPriorityBeanNames.add(candidateBeanName);
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanNames.add(candidateBeanName);
highestPriority = candidatePriority;
}
}
}
}
if (highestPriorityBeanNames.size() > 1) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
return highestPriorityBeanNames.isEmpty() ? null : highestPriorityBeanNames.get(0);
}