InjectionPoint propagated for shortcut bean name resolution as well

Issue: SPR-14400
This commit is contained in:
Juergen Hoeller
2016-06-26 00:18:54 +02:00
parent 4102c62734
commit e15f7efff8
4 changed files with 76 additions and 35 deletions

View File

@@ -51,7 +51,6 @@ import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -529,9 +528,6 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
}
else if (cachedArgument instanceof RuntimeBeanReference) {
return this.beanFactory.getBean(((RuntimeBeanReference) cachedArgument).getBeanName());
}
else {
return cachedArgument;
}
@@ -581,7 +577,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
}
}
}
@@ -665,7 +661,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
this.cachedMethodArguments[i] =
new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
}
}
}
@@ -701,4 +698,24 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
}
/**
* DependencyDescriptor variant with a pre-resolved target bean name.
*/
@SuppressWarnings("serial")
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
private final String shortcutBeanName;
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutBeanName) {
super(original);
this.shortcutBeanName = shortcutBeanName;
}
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
return resolveCandidate(this.shortcutBeanName, beanFactory);
}
}
}

View File

@@ -187,6 +187,21 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
return beanFactory.getBean(beanName);
}
/**
* Resolve a shortcut for this dependency against the given factory, for example
* taking some pre-resolved information into account.
* <p>The resolution algorithm will first attempt to resolve a shortcut through this
* method before going into the regular type matching algorithm across all beans.
* Subclasses may override this method to improve resolution performance based on
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
* @param beanFactory the associated factory
* @return the shortcut result if any, or {@code null} if none
* @since 4.3.1
*/
public Object resolveShortcut(BeanFactory beanFactory) {
return null;
}
/**
* Increase this descriptor's nesting level.

View File

@@ -1024,27 +1024,32 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {