@ -93,6 +93,7 @@ import org.springframework.util.StringUtils;
@@ -93,6 +93,7 @@ import org.springframework.util.StringUtils;
* @author Costin Leau
* @author Chris Beams
* @author Phillip Webb
* @author Stephane Nicoll
* @since 16 April 2001
* @see StaticListableBeanFactory
* @see PropertiesBeanDefinitionReader
@ -296,21 +297,19 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -296,21 +297,19 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return getBean ( beanNames [ 0 ] , requiredType ) ;
}
else if ( beanNames . length > 1 ) {
T primaryBean = null ;
Map < String , Object > candidates = new HashMap < String , Object > ( ) ;
for ( String beanName : beanNames ) {
T beanInstance = getBean ( beanName , requiredType ) ;
if ( isPrimary ( beanName , beanInstance ) ) {
if ( primaryBean ! = null ) {
throw new NoUniqueBeanDefinitionException ( requiredType , beanNames . length ,
"more than one 'primary' bean found of required type: " + Arrays . asList ( beanNames ) ) ;
}
primaryBean = beanInstance ;
}
candidates . put ( beanName , getBean ( beanName , requiredType ) ) ;
}
if ( primaryBean ! = null ) {
return primaryBean ;
String primaryCandidate = determinePrimaryCandidate ( candidates , requiredType ) ;
if ( primaryCandidate ! = null ) {
return getBean ( primaryCandidate , requiredType ) ;
}
throw new NoUniqueBeanDefinitionException ( requiredType , beanNames ) ;
String priorityCandidate = determineHighestPriorityCandidate ( candidates , requiredType ) ;
if ( priorityCandidate ! = null ) {
return getBean ( priorityCandidate , requiredType ) ;
}
throw new NoUniqueBeanDefinitionException ( requiredType , candidates . keySet ( ) ) ;
}
else if ( getParentBeanFactory ( ) ! = null ) {
return getParentBeanFactory ( ) . getBean ( requiredType ) ;
@ -965,7 +964,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -965,7 +964,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null ;
}
if ( matchingBeans . size ( ) > 1 ) {
String primaryBeanName = determinePrimary Candidate ( matchingBeans , descriptor ) ;
String primaryBeanName = determineAutowire Candidate ( matchingBeans , descriptor ) ;
if ( primaryBeanName = = null ) {
throw new NoUniqueBeanDefinitionException ( type , matchingBeans . keySet ( ) ) ;
}
@ -1029,15 +1028,50 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -1029,15 +1028,50 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/ * *
* Determine the primary 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 ) .
*
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type , as returned by { @link # findAutowireCandidates }
* @param descriptor the target dependency to match against
* @return the name of the autowire candidate , or { @code null } if none found
* /
protected String determineAutowireCandidate ( Map < String , Object > candidateBeans ,
DependencyDescriptor descriptor ) {
Class < ? > requiredType = descriptor . getDependencyType ( ) ;
String primaryCandidate =
determinePrimaryCandidate ( candidateBeans , requiredType ) ;
if ( primaryCandidate ! = null ) {
return primaryCandidate ;
}
String priorityCandidate =
determineHighestPriorityCandidate ( candidateBeans , requiredType ) ;
if ( priorityCandidate ! = null ) {
return priorityCandidate ;
}
// Fallback
for ( Map . Entry < String , Object > entry : candidateBeans . entrySet ( ) ) {
String candidateBeanName = entry . getKey ( ) ;
Object beanInstance = entry . getValue ( ) ;
if ( this . resolvableDependencies . values ( ) . contains ( beanInstance ) | |
matchesBeanName ( candidateBeanName , descriptor . getDependencyName ( ) ) ) {
return candidateBeanName ;
}
}
return null ;
}
/ * *
* Determine the primary candidate in the given set of beans .
*
* @param candidateBeans a Map of candidate names and candidate instances
* 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 )
* /
protected String determinePrimaryCandidate ( Map < String , Object > candidateBeans , DependencyDescriptor descriptor ) {
protected String determinePrimaryCandidate ( Map < String , Object > candidateBeans , Class < ? > requiredType ) {
String primaryBeanName = null ;
String fallbackBeanName = null ;
for ( Map . Entry < String , Object > entry : candidateBeans . entrySet ( ) ) {
String candidateBeanName = entry . getKey ( ) ;
Object beanInstance = entry . getValue ( ) ;
@ -1046,7 +1080,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -1046,7 +1080,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
boolean candidateLocal = containsBeanDefinition ( candidateBeanName ) ;
boolean primaryLocal = containsBeanDefinition ( primaryBeanName ) ;
if ( candidateLocal & & primaryLocal ) {
throw new NoUniqueBeanDefinitionException ( desc ripto r. g etDepen dency Type( ) , candidateBeans . size ( ) ,
throw new NoUniqueBeanDefinitionException ( requ iredType , candidateBeans . size ( ) ,
"more than one 'primary' bean found among candidates: " + candidateBeans . keySet ( ) ) ;
}
else if ( candidateLocal ) {
@ -1057,13 +1091,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -1057,13 +1091,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
primaryBeanName = candidateBeanName ;
}
}
if ( primaryBeanName = = null & &
( this . resolvableDependencies . values ( ) . contains ( beanInstance ) | |
matchesBeanName ( candidateBeanName , descriptor . getDependencyName ( ) ) ) ) {
fallbackBeanName = candidateBeanName ;
}
return primaryBeanName ;
}
/ * *
* Determine the candidate with the highest priority in the given set of beans .
*
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority , or { @code null } if none found
* @see # getPriority ( Object )
* /
protected String determineHighestPriorityCandidate ( Map < String , Object > candidateBeans ,
Class < ? > requiredType ) {
String highestPriorityBeanName = null ;
Integer highestPriority = null ;
for ( Map . Entry < String , Object > entry : candidateBeans . entrySet ( ) ) {
String candidateBeanName = entry . getKey ( ) ;
Object beanInstance = entry . getValue ( ) ;
Integer candidatePriority = getPriority ( beanInstance ) ;
if ( candidatePriority ! = null ) {
if ( highestPriorityBeanName ! = null ) {
if ( candidatePriority . equals ( highestPriority ) ) {
throw new NoUniqueBeanDefinitionException ( requiredType , candidateBeans . size ( ) ,
"Multiple beans found with the same priority ('" + highestPriority + "') " +
"among candidates: " + candidateBeans . keySet ( ) ) ;
} else if ( candidatePriority > highestPriority ) {
highestPriorityBeanName = candidateBeanName ;
highestPriority = candidatePriority ;
}
} else {
highestPriorityBeanName = candidateBeanName ;
highestPriority = candidatePriority ;
}
}
}
return ( primaryBeanName ! = null ? primaryBeanName : fallbackBeanName ) ;
return highestPriorityBeanName ;
}
/ * *
@ -1082,6 +1147,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@@ -1082,6 +1147,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
( ( DefaultListableBeanFactory ) parentFactory ) . isPrimary ( beanName , beanInstance ) ) ;
}
/ * *
* Return the priority assigned for the given bean instance by
* the { @code javax . annotation . Priority } annotation .
* < p > If the annotation is not present , returns { @code null } .
*
* @param beanInstance the bean instance to check
* @return the priority assigned to that bean or { @code null } if none is set
* /
protected Integer getPriority ( Object beanInstance ) {
for ( Annotation annotation : beanInstance . getClass ( ) . getAnnotations ( ) ) {
if ( "javax.annotation.Priority" . equals ( annotation . annotationType ( ) . getName ( ) ) ) {
return ( Integer ) AnnotationUtils . getValue ( annotation ) ;
}
}
return null ;
}
/ * *
* Determine whether the given candidate name matches the bean name or the aliases
* stored in this bean definition .