Various DefaultListableBeanFactory clarifications

* getBeanDefinitionNames defensively returns a copy of the bean definition names array.
* copyConfigurationFrom provides an independent AutowireCandidateResolver instance and copies a ConversionService and dependency comparator configuration as well.
* findAutowireCandidates only considers a self reference fallback for direct dependency declarations, not as a collection element.

Issue: SPR-14897
Issue: SPR-14921
Issue: SPR-14965
(cherry picked from commit ac5933a)
This commit is contained in:
Juergen Hoeller
2016-11-30 22:07:55 +01:00
parent a7ba63d425
commit 7ac9f92bc2
4 changed files with 98 additions and 22 deletions

View File

@@ -134,13 +134,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
new LinkedHashSet<PropertyEditorRegistrar>(4);
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
private TypeConverter typeConverter;
/** Custom PropertyEditors to apply to the beans of this factory */
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors =
new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
private TypeConverter typeConverter;
/** String resolvers to apply e.g. to annotation attribute values */
private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<StringValueResolver>();
@@ -921,10 +921,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
setBeanClassLoader(otherFactory.getBeanClassLoader());
setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
setConversionService(otherFactory.getConversionService());
if (otherFactory instanceof AbstractBeanFactory) {
AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
this.customEditors.putAll(otherAbstractFactory.customEditors);
this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
this.customEditors.putAll(otherAbstractFactory.customEditors);
this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
@@ -935,6 +937,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
else {
setTypeConverter(otherFactory.getTypeConverter());
String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
for (String scopeName : otherScopeNames) {
this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
}
}
}

View File

@@ -43,6 +43,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Provider;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
@@ -266,6 +267,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Set a {@link java.util.Comparator} for dependency Lists and arrays.
* @since 4.0
* @see org.springframework.core.OrderComparator
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
*/
@@ -275,6 +277,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Return the dependency comparator for this BeanFactory (may be {@code null}.
* @since 4.0
*/
public Comparator<Object> getDependencyComparator() {
return this.dependencyComparator;
@@ -289,11 +292,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
if (autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
final BeanFactory target = this;
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target);
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
return null;
}
}, getAccessControlContext());
@@ -320,7 +322,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
this.dependencyComparator = otherListableFactory.dependencyComparator;
// A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware...
setAutowireCandidateResolver(BeanUtils.instantiateClass(getAutowireCandidateResolver().getClass()));
// Make resolvable dependencies (e.g. ResourceLoader) available here as well...
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
}
}
@@ -367,7 +372,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public String[] getBeanDefinitionNames() {
if (this.frozenBeanDefinitionNames != null) {
return this.frozenBeanDefinitionNames;
return this.frozenBeanDefinitionNames.clone();
}
else {
return StringUtils.toStringArray(this.beanDefinitionNames);
@@ -1266,8 +1271,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
addCandidateEntry(result, candidateName, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// Consider self references before as a final pass
if (result.isEmpty() && !(descriptor instanceof MultiElementDependencyDescriptor)) {
// Consider self references as a final pass...
// but not as collection elements, just for direct dependency declarations.
for (String candidateName : candidateNames) {
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
addCandidateEntry(result, candidateName, descriptor, requiredType);
@@ -1476,10 +1482,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
Class<?> targetType = mbd.getTargetType();
if (targetType != null && type.isAssignableFrom(targetType) &&
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
// Probably a poxy interfering with target type match -> throw meaningful exception.
// Probably a proxy interfering with target type match -> throw meaningful exception.
Object beanInstance = getSingleton(beanName, false);
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
if (type != beanType) {
if (!type.isAssignableFrom((beanType))) {
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
}
}