Fixed QualifierAnnotationAutowireCandidateResolver's detection of custom qualifier annotations
Issue: SPR-10107
This commit is contained in:
parent
047db8cdf8
commit
c242abada1
|
@ -36,6 +36,7 @@ import org.springframework.core.annotation.AnnotationUtils;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link AutowireCandidateResolver} implementation that matches bean definition qualifiers
|
||||
|
@ -192,7 +193,7 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
foundMeta = true;
|
||||
// Only accept fallback match if @Qualifier annotation has a value...
|
||||
// Otherwise it is just a marker for a custom qualifier annotation.
|
||||
if ((fallbackToMeta && AnnotationUtils.getValue(metaAnn) == null) ||
|
||||
if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
|
||||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ public class QualifierAnnotationAutowireContextTests {
|
|||
RootBeanDefinition person = new RootBeanDefinition(QualifiedPerson.class, cavs, null);
|
||||
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
|
||||
cavs2.addGenericArgumentValue(MARK);
|
||||
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
|
||||
RootBeanDefinition person2 = new RootBeanDefinition(DefaultValueQualifiedPerson.class, cavs2, null);
|
||||
context.registerBeanDefinition(JUERGEN, person);
|
||||
context.registerBeanDefinition(MARK, person2);
|
||||
context.registerBeanDefinition("autowired",
|
||||
|
@ -745,13 +745,25 @@ public class QualifierAnnotationAutowireContextTests {
|
|||
}
|
||||
|
||||
|
||||
@TestQualifierWithDefaultValue
|
||||
private static class DefaultValueQualifiedPerson extends Person {
|
||||
|
||||
public DefaultValueQualifiedPerson() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public DefaultValueQualifiedPerson(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public static @interface TestQualifier {
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public static @interface TestQualifierWithDefaultValue {
|
||||
|
|
|
@ -69,6 +69,21 @@ public abstract class StringUtils {
|
|||
// General convenience methods for working with Strings
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check whether the given String is empty.
|
||||
* <p>This method accepts any Object as an argument, comparing it to
|
||||
* <code>null</code> and the empty String. As a consequence, this method
|
||||
* will never return <code>true</code> for a non-null non-String object.
|
||||
* <p>The Object signature is useful for general attribute handling code
|
||||
* that commonly deals with Strings but generally has to iterate over
|
||||
* Objects since attributes may e.g. be primitive value objects as well.
|
||||
* @param str the candidate String
|
||||
* @since 3.2.1
|
||||
*/
|
||||
public static boolean isEmpty(Object str) {
|
||||
return (str == null || "".equals(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given CharSequence is neither <code>null</code> nor of length 0.
|
||||
* Note: Will return <code>true</code> for a CharSequence that purely consists of whitespace.
|
||||
|
|
Loading…
Reference in New Issue