Honor @Autowired(required=false) at parameter level

Issue: SPR-15268
(cherry picked from commit d74542e)
This commit is contained in:
Juergen Hoeller
2017-05-03 13:42:16 +02:00
parent 2d1b551248
commit beac891ff0
6 changed files with 119 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -111,6 +111,17 @@ public class InjectionPoint {
}
}
/**
* Retrieve a field/parameter annotation of the given type, if any.
* @param annotationType the annotation type to retrieve
* @return the annotation instance, or {@code null} if none found
* @since 4.3.9
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
return (this.field != null ? this.field.getAnnotation(annotationType) :
this.methodParameter.getParameterAnnotation(annotationType));
}
/**
* Return the type declared by the underlying field or method/constructor parameter,
* indicating the injection type.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -309,7 +309,21 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
/**
* Determine whether the given dependency carries a value annotation.
* Determine whether the given dependency declares an autowired annotation,
* checking its required flag.
* @see Autowired#required()
*/
@Override
public boolean isRequired(DependencyDescriptor descriptor) {
if (!super.isRequired(descriptor)) {
return false;
}
Autowired autowired = descriptor.getAnnotation(Autowired.class);
return (autowired == null || autowired.required());
}
/**
* Determine whether the given dependency declares a value annotation.
* @see Value
*/
@Override

View File

@@ -1100,7 +1100,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
@@ -1112,7 +1112,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
@@ -1217,6 +1217,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
private boolean isRequired(DependencyDescriptor descriptor) {
AutowireCandidateResolver resolver = getAutowireCandidateResolver();
return (resolver instanceof SimpleAutowireCandidateResolver ?
((SimpleAutowireCandidateResolver) resolver).isRequired(descriptor) :
descriptor.isRequired());
}
private boolean indicatesMultipleBeans(Class<?> type) {
return (type.isArray() || (type.isInterface() &&
(Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type))));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -40,7 +40,8 @@ import org.springframework.util.ClassUtils;
* @author Juergen Hoeller
* @since 4.0
*/
public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryAware {
public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver
implements BeanFactoryAware {
private BeanFactory beanFactory;
@@ -57,8 +58,8 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!bdHolder.getBeanDefinition().isAutowireCandidate()) {
// if explicitly false, do not proceed with any other checks
if (!super.isAutowireCandidate(bdHolder, descriptor)) {
// If explicitly false, do not proceed with any other checks...
return false;
}
return (descriptor == null || checkGenericTypeMatch(bdHolder, descriptor));
@@ -166,23 +167,4 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
return null;
}
/**
* This implementation always returns {@code null}, leaving suggested value support up
* to subclasses.
*/
@Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
return null;
}
/**
* This implementation always returns {@code null}, leaving lazy resolution support up
* to subclasses.
*/
@Override
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) {
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -16,7 +16,6 @@
package org.springframework.beans.factory.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -27,20 +26,27 @@ import org.springframework.beans.factory.config.DependencyDescriptor;
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
* @see BeanDefinition#isAutowireCandidate()
*/
public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver {
/**
* Determine if the provided bean definition is an autowire candidate.
* <p>To be considered a candidate the bean's <em>autowire-candidate</em>
* attribute must not have been set to 'false'.
*/
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
return bdHolder.getBeanDefinition().isAutowireCandidate();
}
/**
* Determine whether the given descriptor is effectively required.
* <p>The default implementation checks {@link DependencyDescriptor#isRequired()}.
* @param descriptor the descriptor for the target method parameter or field
* @return whether the descriptor is marked as required or possibly indicating
* non-required status some other way (e.g. through a parameter annotation)
* @since 4.3.9
* @see DependencyDescriptor#isRequired()
*/
public boolean isRequired(DependencyDescriptor descriptor) {
return descriptor.isRequired();
}
@Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
return null;