@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2015 the original author or authors .
* Copyright 2002 - 2016 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 .
@ -17,28 +17,32 @@
@@ -17,28 +17,32 @@
package org.springframework.beans.factory.annotation ;
import java.lang.reflect.Method ;
import java.util.function.Predicate ;
import org.springframework.beans.BeansException ;
import org.springframework.beans.factory.BeanFactory ;
import org.springframework.beans.factory.BeanFactoryUtils ;
import org.springframework.beans.factory.NoSuchBeanDefinitionException ;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException ;
import org.springframework.beans.factory.config.BeanDefinition ;
import org.springframework.beans.factory.config.ConfigurableBeanFactory ;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory ;
import org.springframework.beans.factory.support.AbstractBeanDefinition ;
import org.springframework.beans.factory.support.AutowireCandidateQualifier ;
import org.springframework.beans.factory.support.RootBeanDefinition ;
import org.springframework.core.annotation.AnnotationUtils ;
import org.springframework.util.ObjectUtils ;
import org.springframework.util.Assert ;
/ * *
* Convenience methods performing bean lookups related to annotations , for example
* Spring ' s { @link Qualifier @Qualifier } annotation .
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Chris Beams
* @since 3 . 1 . 2
* @see BeanFactoryUtils
* /
public class BeanFactoryAnnotationUtils {
public abstract class BeanFactoryAnnotationUtils {
/ * *
* Obtain a bean of type { @code T } from the given { @code BeanFactory } declaring a
@ -48,9 +52,16 @@ public class BeanFactoryAnnotationUtils {
@@ -48,9 +52,16 @@ public class BeanFactoryAnnotationUtils {
* @param beanType the type of bean to retrieve
* @param qualifier the qualifier for selecting between multiple bean matches
* @return the matching bean of type { @code T } ( never { @code null } )
* @throws NoUniqueBeanDefinitionException if multiple matching beans of type { @code T } found
* @throws NoSuchBeanDefinitionException if no matching bean of type { @code T } found
* @throws BeansException if the bean could not be created
* @see BeanFactory # getBean ( Class )
* /
public static < T > T qualifiedBeanOfType ( BeanFactory beanFactory , Class < T > beanType , String qualifier ) {
public static < T > T qualifiedBeanOfType ( BeanFactory beanFactory , Class < T > beanType , String qualifier )
throws BeansException {
Assert . notNull ( beanFactory , "BeanFactory must not be null" ) ;
if ( beanFactory instanceof ConfigurableListableBeanFactory ) {
// Full qualifier matching supported.
return qualifiedBeanOfType ( ( ConfigurableListableBeanFactory ) beanFactory , beanType , qualifier ) ;
@ -74,16 +85,14 @@ public class BeanFactoryAnnotationUtils {
@@ -74,16 +85,14 @@ public class BeanFactoryAnnotationUtils {
* @param beanType the type of bean to retrieve
* @param qualifier the qualifier for selecting between multiple bean matches
* @return the matching bean of type { @code T } ( never { @code null } )
* @throws NoSuchBeanDefinitionException if no matching bean of type { @code T } found
* /
private static < T > T qualifiedBeanOfType ( ConfigurableListableBeanFactory bf , Class < T > beanType , String qualifier ) {
String [ ] candidateBeans = BeanFactoryUtils . beanNamesForTypeIncludingAncestors ( bf , beanType ) ;
String matchingBean = null ;
for ( String beanName : candidateBeans ) {
if ( isQualifierMatch ( qualifier , beanName , bf ) ) {
if ( isQualifierMatch ( qualifier : : equals , beanName , bf ) ) {
if ( matchingBean ! = null ) {
throw new NoSuchBeanDefinitionException ( qualifier , "No unique " + beanType . getSimpleName ( ) +
" bean found for qualifier '" + qualifier + "'" ) ;
throw new NoUniqueBeanDefinitionException ( beanType , matchingBean , beanName ) ;
}
matchingBean = beanName ;
}
@ -105,40 +114,54 @@ public class BeanFactoryAnnotationUtils {
@@ -105,40 +114,54 @@ public class BeanFactoryAnnotationUtils {
* Check whether the named bean declares a qualifier of the given name .
* @param qualifier the qualifier to match
* @param beanName the name of the candidate bean
* @param bf the { @code BeanFactory } from which to retrieve the named bean
* @param beanFactory the { @code BeanFactory } from which to retrieve the named bean
* @return { @code true } if either the bean definition ( in the XML case )
* or the bean ' s factory method ( in the { @code @Bean } case ) defines a matching
* qualifier value ( through { @code < qualifier > } or { @code @Qualifier } )
* @since 5 . 0
* /
private static boolean isQualifierMatch ( String qualifier , String beanName , ConfigurableListableBeanFactory bf ) {
if ( bf . containsBean ( beanName ) ) {
public static boolean isQualifierMatch ( Predicate < String > qualifier , String beanName , BeanFactory beanFactory ) {
// Try quick bean name or alias match first...
if ( qualifier . test ( beanName ) ) {
return true ;
}
if ( beanFactory ! = null ) {
for ( String alias : beanFactory . getAliases ( beanName ) ) {
if ( qualifier . test ( alias ) ) {
return true ;
}
}
try {
BeanDefinition bd = bf . getMergedBeanDefinition ( beanName ) ;
// Explicit qualifier metadata on bean definition? (typically in XML definition)
if ( bd instanceof AbstractBeanDefinition ) {
AbstractBeanDefinition abd = ( AbstractBeanDefinition ) bd ;
AutowireCandidateQualifier candidate = abd . getQualifier ( Qualifier . class . getName ( ) ) ;
if ( ( candidate ! = null & & qualifier . equals ( candidate . getAttribute ( AutowireCandidateQualifier . VALUE_KEY ) ) ) | |
qualifier . equals ( beanName ) | | ObjectUtils . containsElement ( bf . getAliases ( beanName ) , qualifier ) ) {
return true ;
if ( beanFactory instanceof ConfigurableBeanFactory ) {
BeanDefinition bd = ( ( ConfigurableBeanFactory ) beanFactory ) . getMergedBeanDefinition ( beanName ) ;
// Explicit qualifier metadata on bean definition? (typically in XML definition)
if ( bd instanceof AbstractBeanDefinition ) {
AbstractBeanDefinition abd = ( AbstractBeanDefinition ) bd ;
AutowireCandidateQualifier candidate = abd . getQualifier ( Qualifier . class . getName ( ) ) ;
if ( candidate ! = null ) {
Object value = candidate . getAttribute ( AutowireCandidateQualifier . VALUE_KEY ) ;
if ( value ! = null & & qualifier . test ( value . toString ( ) ) ) {
return true ;
}
}
}
}
// Corresponding qualifier on factory method? (typically in configuration class)
if ( bd instanceof RootBeanDefinition ) {
Method factoryMethod = ( ( RootBeanDefinition ) bd ) . getResolvedFactoryMethod ( ) ;
if ( factoryMethod ! = null ) {
Qualifier targetAnnotation = AnnotationUtils . getAnnotation ( factoryMethod , Qualifier . class ) ;
if ( targetAnnotation ! = null ) {
return qualifier . equals ( targetAnnotation . value ( ) ) ;
// Corresponding qualifier on factory method? (typically in configuration class)
if ( bd instanceof RootBeanDefinition ) {
Method factoryMethod = ( ( RootBeanDefinition ) bd ) . getResolvedFactoryMethod ( ) ;
if ( factoryMethod ! = null ) {
Qualifier targetAnnotation = AnnotationUtils . getAnnotation ( factoryMethod , Qualifier . class ) ;
if ( targetAnnotation ! = null ) {
return qual ifier . test ( targetAnnotation . value ( ) ) ;
}
}
}
}
// Corresponding qualifier on bean implementation class? (for custom user types)
Class < ? > beanType = bf . getType ( beanName ) ;
Class < ? > beanType = beanFactory . getType ( beanName ) ;
if ( beanType ! = null ) {
Qualifier targetAnnotation = AnnotationUtils . getAnnotation ( beanType , Qualifier . class ) ;
if ( targetAnnotation ! = null ) {
return qualifier . equal s ( targetAnnotation . value ( ) ) ;
return qualifier . t est ( targetAnnotation . value ( ) ) ;
}
}
}