DefaultListableBeanFactory does not trigger early candidate creation ahead of primary bean selection
Issue: SPR-14611
(cherry picked from commit c4fcdb6
)
This commit is contained in:
parent
74bf659c56
commit
a7849b2861
|
@ -986,38 +986,47 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
|
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||||
Assert.notNull(requiredType, "Required type must not be null");
|
Assert.notNull(requiredType, "Required type must not be null");
|
||||||
String[] beanNames = getBeanNamesForType(requiredType);
|
String[] candidateNames = getBeanNamesForType(requiredType);
|
||||||
|
|
||||||
if (beanNames.length > 1) {
|
if (candidateNames.length > 1) {
|
||||||
ArrayList<String> autowireCandidates = new ArrayList<String>();
|
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
|
||||||
for (String beanName : beanNames) {
|
for (String beanName : candidateNames) {
|
||||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||||
autowireCandidates.add(beanName);
|
autowireCandidates.add(beanName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!autowireCandidates.isEmpty()) {
|
if (!autowireCandidates.isEmpty()) {
|
||||||
beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beanNames.length == 1) {
|
if (candidateNames.length == 1) {
|
||||||
String beanName = beanNames[0];
|
String beanName = candidateNames[0];
|
||||||
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
|
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
|
||||||
}
|
}
|
||||||
else if (beanNames.length > 1) {
|
else if (candidateNames.length > 1) {
|
||||||
Map<String, Object> candidates = new LinkedHashMap<String, Object>();
|
Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
|
||||||
for (String beanName : beanNames) {
|
for (String candidateName : candidateNames) {
|
||||||
candidates.put(beanName, getBean(beanName, requiredType, args));
|
if (containsSingleton(candidateName)) {
|
||||||
|
candidates.put(candidateName, getBean(candidateName, requiredType, args));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
candidates.put(candidateName, getType(candidateName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
String candidateName = determinePrimaryCandidate(candidates, requiredType);
|
||||||
if (primaryCandidate != null) {
|
if (candidateName == null) {
|
||||||
return new NamedBeanHolder<T>(primaryCandidate, getBean(primaryCandidate, requiredType, args));
|
candidateName = determineHighestPriorityCandidate(candidates, requiredType);
|
||||||
}
|
}
|
||||||
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
if (candidateName != null) {
|
||||||
if (priorityCandidate != null) {
|
Object beanInstance = candidates.get(candidateName);
|
||||||
return new NamedBeanHolder<T>(priorityCandidate, getBean(priorityCandidate, requiredType, args));
|
if (beanInstance instanceof Class) {
|
||||||
|
beanInstance = getBean(candidateName, requiredType, args);
|
||||||
|
}
|
||||||
|
return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
|
||||||
}
|
}
|
||||||
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
|
||||||
}
|
}
|
||||||
|
@ -1086,9 +1095,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String autowiredBeanName;
|
||||||
|
Object instanceCandidate;
|
||||||
|
|
||||||
if (matchingBeans.size() > 1) {
|
if (matchingBeans.size() > 1) {
|
||||||
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
|
||||||
if (primaryBeanName == null) {
|
if (autowiredBeanName == null) {
|
||||||
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
|
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
|
||||||
return descriptor.resolveNotUnique(type, matchingBeans);
|
return descriptor.resolveNotUnique(type, matchingBeans);
|
||||||
}
|
}
|
||||||
|
@ -1099,17 +1112,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (autowiredBeanNames != null) {
|
instanceCandidate = matchingBeans.get(autowiredBeanName);
|
||||||
autowiredBeanNames.add(primaryBeanName);
|
|
||||||
}
|
|
||||||
return matchingBeans.get(primaryBeanName);
|
|
||||||
}
|
}
|
||||||
// We have exactly one match.
|
else {
|
||||||
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
// We have exactly one match.
|
||||||
|
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
|
||||||
|
autowiredBeanName = entry.getKey();
|
||||||
|
instanceCandidate = entry.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
if (autowiredBeanNames != null) {
|
if (autowiredBeanNames != null) {
|
||||||
autowiredBeanNames.add(entry.getKey());
|
autowiredBeanNames.add(autowiredBeanName);
|
||||||
}
|
}
|
||||||
return entry.getValue();
|
return (instanceCandidate instanceof Class ?
|
||||||
|
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
||||||
|
@ -1122,9 +1138,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
Class<?> type = descriptor.getDependencyType();
|
Class<?> type = descriptor.getDependencyType();
|
||||||
if (type.isArray()) {
|
if (type.isArray()) {
|
||||||
Class<?> componentType = type.getComponentType();
|
Class<?> componentType = type.getComponentType();
|
||||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
|
||||||
targetDesc.increaseNestingLevel();
|
new MultiElementDependencyDescriptor(descriptor));
|
||||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);
|
|
||||||
if (matchingBeans.isEmpty()) {
|
if (matchingBeans.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1143,9 +1158,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
if (elementType == null) {
|
if (elementType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
|
||||||
targetDesc.increaseNestingLevel();
|
new MultiElementDependencyDescriptor(descriptor));
|
||||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);
|
|
||||||
if (matchingBeans.isEmpty()) {
|
if (matchingBeans.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1168,9 +1182,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
if (valueType == null) {
|
if (valueType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);
|
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
|
||||||
targetDesc.increaseNestingLevel();
|
new MultiElementDependencyDescriptor(descriptor));
|
||||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);
|
|
||||||
if (matchingBeans.isEmpty()) {
|
if (matchingBeans.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1239,7 +1252,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
for (String candidateName : candidateNames) {
|
for (String candidateName : candidateNames) {
|
||||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
||||||
|
@ -1247,14 +1260,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
||||||
for (String candidateName : candidateNames) {
|
for (String candidateName : candidateNames) {
|
||||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.isEmpty()) {
|
if (result.isEmpty()) {
|
||||||
// Consider self references before as a final pass
|
// Consider self references before as a final pass
|
||||||
for (String candidateName : candidateNames) {
|
for (String candidateName : candidateNames) {
|
||||||
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
addCandidateEntry(result, candidateName, descriptor, requiredType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1262,31 +1275,46 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an entry to the candidate map: a bean instance if available or just the resolved
|
||||||
|
* type, preventing early bean initialization ahead of primary candidate selection.
|
||||||
|
*/
|
||||||
|
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
|
||||||
|
DependencyDescriptor descriptor, Class<?> requiredType) {
|
||||||
|
|
||||||
|
if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) {
|
||||||
|
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
candidates.put(candidateName, getType(candidateName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the autowire candidate in the given set of beans.
|
* Determine the autowire candidate in the given set of beans.
|
||||||
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
|
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
|
||||||
* @param candidateBeans a Map of candidate names and candidate instances
|
* @param candidates a Map of candidate names and candidate instances
|
||||||
* that match the required type, as returned by {@link #findAutowireCandidates}
|
* that match the required type, as returned by {@link #findAutowireCandidates}
|
||||||
* @param descriptor the target dependency to match against
|
* @param descriptor the target dependency to match against
|
||||||
* @return the name of the autowire candidate, or {@code null} if none found
|
* @return the name of the autowire candidate, or {@code null} if none found
|
||||||
*/
|
*/
|
||||||
protected String determineAutowireCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
|
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
|
||||||
Class<?> requiredType = descriptor.getDependencyType();
|
Class<?> requiredType = descriptor.getDependencyType();
|
||||||
String primaryCandidate = determinePrimaryCandidate(candidateBeans, requiredType);
|
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
|
||||||
if (primaryCandidate != null) {
|
if (primaryCandidate != null) {
|
||||||
return primaryCandidate;
|
return primaryCandidate;
|
||||||
}
|
}
|
||||||
String priorityCandidate = determineHighestPriorityCandidate(candidateBeans, requiredType);
|
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
|
||||||
if (priorityCandidate != null) {
|
if (priorityCandidate != null) {
|
||||||
return priorityCandidate;
|
return priorityCandidate;
|
||||||
}
|
}
|
||||||
// Fallback
|
// Fallback
|
||||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||||
String candidateBeanName = entry.getKey();
|
String candidateName = entry.getKey();
|
||||||
Object beanInstance = entry.getValue();
|
Object beanInstance = entry.getValue();
|
||||||
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
|
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
|
||||||
matchesBeanName(candidateBeanName, descriptor.getDependencyName())) {
|
matchesBeanName(candidateName, descriptor.getDependencyName())) {
|
||||||
return candidateBeanName;
|
return candidateName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1294,15 +1322,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the primary candidate in the given set of beans.
|
* Determine the primary candidate in the given set of beans.
|
||||||
* @param candidateBeans a Map of candidate names and candidate instances
|
* @param candidates a Map of candidate names and candidate instances
|
||||||
* that match the required type
|
* (or candidate classes if not created yet) that match the required type
|
||||||
* @param requiredType the target dependency type to match against
|
* @param requiredType the target dependency type to match against
|
||||||
* @return the name of the primary candidate, or {@code null} if none found
|
* @return the name of the primary candidate, or {@code null} if none found
|
||||||
* @see #isPrimary(String, Object)
|
* @see #isPrimary(String, Object)
|
||||||
*/
|
*/
|
||||||
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||||
String primaryBeanName = null;
|
String primaryBeanName = null;
|
||||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||||
String candidateBeanName = entry.getKey();
|
String candidateBeanName = entry.getKey();
|
||||||
Object beanInstance = entry.getValue();
|
Object beanInstance = entry.getValue();
|
||||||
if (isPrimary(candidateBeanName, beanInstance)) {
|
if (isPrimary(candidateBeanName, beanInstance)) {
|
||||||
|
@ -1310,8 +1338,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
||||||
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
||||||
if (candidateLocal && primaryLocal) {
|
if (candidateLocal && primaryLocal) {
|
||||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||||
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
|
"more than one 'primary' bean found among candidates: " + candidates.keySet());
|
||||||
}
|
}
|
||||||
else if (candidateLocal) {
|
else if (candidateLocal) {
|
||||||
primaryBeanName = candidateBeanName;
|
primaryBeanName = candidateBeanName;
|
||||||
|
@ -1326,29 +1354,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the candidate with the highest priority in the given set of beans. As
|
* Determine the candidate with the highest priority in the given set of beans.
|
||||||
* defined by the {@link org.springframework.core.Ordered} interface, the lowest
|
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
|
||||||
* value has the highest priority.
|
* {@link org.springframework.core.Ordered} interface, the lowest value has
|
||||||
* @param candidateBeans a Map of candidate names and candidate instances
|
* the highest priority.
|
||||||
* that match the required type
|
* @param candidates a Map of candidate names and candidate instances
|
||||||
|
* (or candidate classes if not created yet) that match the required type
|
||||||
* @param requiredType the target dependency type to match against
|
* @param requiredType the target dependency type to match against
|
||||||
* @return the name of the candidate with the highest priority,
|
* @return the name of the candidate with the highest priority,
|
||||||
* or {@code null} if none found
|
* or {@code null} if none found
|
||||||
* @see #getPriority(Object)
|
* @see #getPriority(Object)
|
||||||
*/
|
*/
|
||||||
protected String determineHighestPriorityCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
|
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
|
||||||
String highestPriorityBeanName = null;
|
String highestPriorityBeanName = null;
|
||||||
Integer highestPriority = null;
|
Integer highestPriority = null;
|
||||||
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
|
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
|
||||||
String candidateBeanName = entry.getKey();
|
String candidateBeanName = entry.getKey();
|
||||||
Object beanInstance = entry.getValue();
|
Object beanInstance = entry.getValue();
|
||||||
Integer candidatePriority = getPriority(beanInstance);
|
Integer candidatePriority = getPriority(beanInstance);
|
||||||
if (candidatePriority != null) {
|
if (candidatePriority != null) {
|
||||||
if (highestPriorityBeanName != null) {
|
if (highestPriorityBeanName != null) {
|
||||||
if (candidatePriority.equals(highestPriority)) {
|
if (candidatePriority.equals(highestPriority)) {
|
||||||
throw new NoUniqueBeanDefinitionException(requiredType, candidateBeans.size(),
|
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
|
||||||
"Multiple beans found with the same priority ('" + highestPriority + "') " +
|
"Multiple beans found with the same priority ('" + highestPriority +
|
||||||
"among candidates: " + candidateBeans.keySet());
|
"') among candidates: " + candidates.keySet());
|
||||||
}
|
}
|
||||||
else if (candidatePriority < highestPriority) {
|
else if (candidatePriority < highestPriority) {
|
||||||
highestPriorityBeanName = candidateBeanName;
|
highestPriorityBeanName = candidateBeanName;
|
||||||
|
@ -1529,7 +1558,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
private class OptionalDependencyFactory {
|
private class OptionalDependencyFactory {
|
||||||
|
|
||||||
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
|
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
|
||||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
|
||||||
@Override
|
@Override
|
||||||
public boolean isRequired() {
|
public boolean isRequired() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1540,7 +1569,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
super.resolveCandidate(beanName, requiredType, beanFactory));
|
super.resolveCandidate(beanName, requiredType, beanFactory));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
descriptorToUse.increaseNestingLevel();
|
|
||||||
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
|
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1558,9 +1586,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
private final String beanName;
|
private final String beanName;
|
||||||
|
|
||||||
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
|
public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) {
|
||||||
this.descriptor = new DependencyDescriptor(descriptor);
|
this.descriptor = new NestedDependencyDescriptor(descriptor);
|
||||||
this.descriptor.increaseNestingLevel();
|
this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass);
|
||||||
this.optional = this.descriptor.getDependencyType().equals(javaUtilOptionalClass);
|
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1676,7 +1703,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
if (beanDefinition == null) {
|
if (beanDefinition == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<Object> sources = new ArrayList<Object>();
|
List<Object> sources = new ArrayList<Object>(2);
|
||||||
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
|
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
|
||||||
if (factoryMethod != null) {
|
if (factoryMethod != null) {
|
||||||
sources.add(factoryMethod);
|
sources.add(factoryMethod);
|
||||||
|
@ -1699,4 +1726,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class NestedDependencyDescriptor extends DependencyDescriptor {
|
||||||
|
|
||||||
|
public NestedDependencyDescriptor(DependencyDescriptor original) {
|
||||||
|
super(original);
|
||||||
|
increaseNestingLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor {
|
||||||
|
|
||||||
|
public MultiElementDependencyDescriptor(DependencyDescriptor original) {
|
||||||
|
super(original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1435,12 +1435,14 @@ public class DefaultListableBeanFactoryTests {
|
||||||
public void testGetBeanByTypeWithPrimary() throws Exception {
|
public void testGetBeanByTypeWithPrimary() throws Exception {
|
||||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||||
|
bd1.setLazyInit(true);
|
||||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||||
bd2.setPrimary(true);
|
bd2.setPrimary(true);
|
||||||
lbf.registerBeanDefinition("bd1", bd1);
|
lbf.registerBeanDefinition("bd1", bd1);
|
||||||
lbf.registerBeanDefinition("bd2", bd2);
|
lbf.registerBeanDefinition("bd2", bd2);
|
||||||
TestBean bean = lbf.getBean(TestBean.class);
|
TestBean bean = lbf.getBean(TestBean.class);
|
||||||
assertThat(bean.getBeanName(), equalTo("bd2"));
|
assertThat(bean.getBeanName(), equalTo("bd2"));
|
||||||
|
assertFalse(lbf.containsSingleton("bd1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1760,24 +1762,6 @@ public class DefaultListableBeanFactoryTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
|
|
||||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
|
||||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
|
||||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
|
||||||
lbf.registerBeanDefinition("test", bd);
|
|
||||||
lbf.registerBeanDefinition("spouse", bd2);
|
|
||||||
try {
|
|
||||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
|
||||||
fail("Should have thrown UnsatisfiedDependencyException");
|
|
||||||
}
|
|
||||||
catch (UnsatisfiedDependencyException ex) {
|
|
||||||
// expected
|
|
||||||
assertTrue(ex.getMessage().contains("test"));
|
|
||||||
assertTrue(ex.getMessage().contains("spouse"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAutowireBeanByTypeWithDependencyCheck() {
|
public void testAutowireBeanByTypeWithDependencyCheck() {
|
||||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
|
|
|
@ -1146,12 +1146,15 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||||
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
|
RootBeanDefinition tb1 = new RootBeanDefinition(TestBean.class);
|
||||||
tb1.setPrimary(true);
|
tb1.setPrimary(true);
|
||||||
bf.registerBeanDefinition("testBean1", tb1);
|
bf.registerBeanDefinition("testBean1", tb1);
|
||||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
RootBeanDefinition tb2 = new RootBeanDefinition(TestBean.class);
|
||||||
|
tb2.setLazyInit(true);
|
||||||
|
bf.registerBeanDefinition("testBean2", tb2);
|
||||||
|
|
||||||
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||||
assertSame(bf.getBean("testBean1"), bean.getTestBean());
|
assertSame(bf.getBean("testBean1"), bean.getTestBean());
|
||||||
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
|
assertSame(bf.getBean("testBean1"), bean.getOptionalTestBean());
|
||||||
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
|
assertSame(bf.getBean("testBean1"), bean.getUniqueTestBean());
|
||||||
|
assertFalse(bf.containsSingleton("testBean2"));
|
||||||
bf.destroySingletons();
|
bf.destroySingletons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -48,9 +48,10 @@ public abstract class OrderUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the order on the specified {@code type}.
|
* Return the order on the specified {@code type}.
|
||||||
* <p>Take care of {@link Order @Order} and {@code @javax.annotation.Priority}.
|
* <p>Takes care of {@link Order @Order} and {@code @javax.annotation.Priority}.
|
||||||
* @param type the type to handle
|
* @param type the type to handle
|
||||||
* @return the order value, or {@code null} if none can be found
|
* @return the order value, or {@code null} if none can be found
|
||||||
|
* @see #getPriority(Class)
|
||||||
*/
|
*/
|
||||||
public static Integer getOrder(Class<?> type) {
|
public static Integer getOrder(Class<?> type) {
|
||||||
return getOrder(type, null);
|
return getOrder(type, null);
|
||||||
|
@ -59,9 +60,10 @@ public abstract class OrderUtils {
|
||||||
/**
|
/**
|
||||||
* Return the order on the specified {@code type}, or the specified
|
* Return the order on the specified {@code type}, or the specified
|
||||||
* default value if none can be found.
|
* default value if none can be found.
|
||||||
* <p>Take care of {@link Order @Order} and {@code @javax.annotation.Priority}.
|
* <p>Takes care of {@link Order @Order} and {@code @javax.annotation.Priority}.
|
||||||
* @param type the type to handle
|
* @param type the type to handle
|
||||||
* @return the priority value, or the specified default order if none can be found
|
* @return the priority value, or the specified default order if none can be found
|
||||||
|
* @see #getPriority(Class)
|
||||||
*/
|
*/
|
||||||
public static Integer getOrder(Class<?> type, Integer defaultOrder) {
|
public static Integer getOrder(Class<?> type, Integer defaultOrder) {
|
||||||
Order order = AnnotationUtils.findAnnotation(type, Order.class);
|
Order order = AnnotationUtils.findAnnotation(type, Order.class);
|
||||||
|
|
Loading…
Reference in New Issue