Consistently evaluate defaultCandidate flag on constructors and methods
Closes gh-33762
This commit is contained in:
parent
6f9413ba31
commit
ee1fe8a1e9
|
@ -154,26 +154,35 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
|||
*/
|
||||
@Override
|
||||
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
|
||||
boolean match = super.isAutowireCandidate(bdHolder, descriptor);
|
||||
if (match) {
|
||||
match = checkQualifiers(bdHolder, descriptor.getAnnotations());
|
||||
if (match) {
|
||||
if (!super.isAutowireCandidate(bdHolder, descriptor)) {
|
||||
return false;
|
||||
}
|
||||
Boolean checked = checkQualifiers(bdHolder, descriptor.getAnnotations());
|
||||
if (checked != Boolean.FALSE) {
|
||||
MethodParameter methodParam = descriptor.getMethodParameter();
|
||||
if (methodParam != null) {
|
||||
Method method = methodParam.getMethod();
|
||||
if (method == null || void.class == method.getReturnType()) {
|
||||
match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
|
||||
Boolean methodChecked = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
|
||||
if (methodChecked != null && checked == null) {
|
||||
checked = methodChecked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
return (checked == Boolean.TRUE ||
|
||||
(checked == null && ((RootBeanDefinition) bdHolder.getBeanDefinition()).isDefaultCandidate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the given qualifier annotations against the candidate bean definition.
|
||||
* @return {@code false} if a qualifier has been found but not matched,
|
||||
* {@code true} if a qualifier has been found and matched,
|
||||
* {@code null} if no qualifier has been found at all
|
||||
*/
|
||||
protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
|
||||
|
||||
@Nullable
|
||||
protected Boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
|
||||
boolean qualifierFound = false;
|
||||
if (!ObjectUtils.isEmpty(annotationsToSearch)) {
|
||||
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
|
||||
|
@ -217,7 +226,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
|||
}
|
||||
}
|
||||
}
|
||||
return (qualifierFound || ((RootBeanDefinition) bdHolder.getBeanDefinition()).isDefaultCandidate());
|
||||
return (qualifierFound ? true : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -195,6 +195,28 @@ class BeanMethodQualificationTests {
|
|||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void customWithConstructor() {
|
||||
AnnotationConfigApplicationContext ctx = context(CustomConfig.class, CustomPojoWithConstructor.class);
|
||||
|
||||
CustomPojoWithConstructor pojo = ctx.getBean(CustomPojoWithConstructor.class);
|
||||
assertThat(pojo.plainBean).isNull();
|
||||
assertThat(pojo.testBean.getName()).isEqualTo("interesting");
|
||||
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void customWithMethod() {
|
||||
AnnotationConfigApplicationContext ctx = context(CustomConfig.class, CustomPojoWithMethod.class);
|
||||
|
||||
CustomPojoWithMethod pojo = ctx.getBean(CustomPojoWithMethod.class);
|
||||
assertThat(pojo.plainBean).isNull();
|
||||
assertThat(pojo.testBean.getName()).isEqualTo("interesting");
|
||||
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void beanNamesForAnnotation() {
|
||||
AnnotationConfigApplicationContext ctx = context(StandardConfig.class);
|
||||
|
@ -327,6 +349,7 @@ class BeanMethodQualificationTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class EffectivePrimaryConfig {
|
||||
|
||||
|
@ -346,6 +369,7 @@ class BeanMethodQualificationTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Component @Lazy
|
||||
static class StandardPojo {
|
||||
|
||||
|
@ -418,6 +442,35 @@ class BeanMethodQualificationTests {
|
|||
}
|
||||
|
||||
|
||||
@InterestingPojo
|
||||
static class CustomPojoWithConstructor {
|
||||
|
||||
TestBean plainBean;
|
||||
|
||||
TestBean testBean;
|
||||
|
||||
public CustomPojoWithConstructor(Optional<TestBean> plainBean, @InterestingNeed TestBean testBean) {
|
||||
this.plainBean = plainBean.orElse(null);
|
||||
this.testBean = testBean;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@InterestingPojo
|
||||
static class CustomPojoWithMethod {
|
||||
|
||||
TestBean plainBean;
|
||||
|
||||
TestBean testBean;
|
||||
|
||||
@Autowired
|
||||
public void applyDependencies(Optional<TestBean> plainBean, @InterestingNeed TestBean testBean) {
|
||||
this.plainBean = plainBean.orElse(null);
|
||||
this.testBean = testBean;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Boring {
|
||||
|
|
Loading…
Reference in New Issue