Introduce AutowireCandidateResolver.cloneIfNecessary() method

Closes gh-25131
This commit is contained in:
Juergen Hoeller 2020-05-26 23:33:39 +02:00
parent f9aae8dd5a
commit dfa948c2ca
4 changed files with 63 additions and 8 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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,6 +16,7 @@
package org.springframework.beans.factory.support;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.lang.Nullable;
@ -99,4 +100,22 @@ public interface AutowireCandidateResolver {
return null;
}
/**
* Return a clone of this resolver instance if necessary, retaining its local
* configuration and allowing for the cloned instance to get associated with
* a new bean factory, or this original instance if there is no such state.
* <p>The default implementation creates a separate instance via the default
* class constructor, assuming no specific configuration state to copy.
* Subclasses may override this with custom configuration state handling
* or with standard {@link Cloneable} support (as implemented by Spring's
* own configurable {@code AutowireCandidateResolver} variants), or simply
* return {@code this} (as in {@link SimpleAutowireCandidateResolver}).
* @since 5.2.7
* @see GenericTypeAwareAutowireCandidateResolver#cloneIfNecessary()
* @see DefaultListableBeanFactory#copyConfigurationFrom
*/
default AutowireCandidateResolver cloneIfNecessary() {
return BeanUtils.instantiateClass(getClass());
}
}

View File

@ -46,7 +46,6 @@ import java.util.stream.Stream;
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;
@ -157,7 +156,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private Comparator<Object> dependencyComparator;
/** Resolver to use for checking if a bean definition is an autowire candidate. */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;
/** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
@ -328,8 +327,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
this.dependencyComparator = otherListableFactory.dependencyComparator;
// A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware...
setAutowireCandidateResolver(
BeanUtils.instantiateClass(otherListableFactory.getAutowireCandidateResolver().getClass()));
setAutowireCandidateResolver(otherListableFactory.getAutowireCandidateResolver().cloneIfNecessary());
// Make resolvable dependencies (e.g. ResourceLoader) available here as well...
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2020 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.
@ -43,7 +43,7 @@ import org.springframework.util.ClassUtils;
* @since 4.0
*/
public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver
implements BeanFactoryAware {
implements BeanFactoryAware, Cloneable {
@Nullable
private BeanFactory beanFactory;
@ -177,4 +177,21 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan
return null;
}
/**
* This implementation clones all instance fields through standard
* {@link Cloneable} support, allowing for subsequent reconfiguration
* of the cloned instance through a fresh {@link #setBeanFactory} call.
* @see #clone()
*/
@Override
public AutowireCandidateResolver cloneIfNecessary() {
try {
return (AutowireCandidateResolver) clone();
}
catch (CloneNotSupportedException ex) {
throw new IllegalStateException(ex);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2020 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.
@ -30,6 +30,13 @@ import org.springframework.lang.Nullable;
*/
public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver {
/**
* Shared instance of {@code SimpleAutowireCandidateResolver}.
* @since 5.2.7
*/
public static final SimpleAutowireCandidateResolver INSTANCE = new SimpleAutowireCandidateResolver();
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
return bdHolder.getBeanDefinition().isAutowireCandidate();
@ -40,6 +47,11 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
return descriptor.isRequired();
}
@Override
public boolean hasQualifier(DependencyDescriptor descriptor) {
return false;
}
@Override
@Nullable
public Object getSuggestedValue(DependencyDescriptor descriptor) {
@ -52,4 +64,13 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
return null;
}
/**
* This implementation returns {@code this} as-is.
* @see #INSTANCE
*/
@Override
public AutowireCandidateResolver cloneIfNecessary() {
return this;
}
}