spring DefaultListableBeanFactory 源码
spring DefaultListableBeanFactory 代码
文件路径:/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
/*
* Copyright 2002-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serial;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import jakarta.inject.Provider;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.core.log.LogMessage;
import org.springframework.core.metrics.StartupStep;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.CompositeIterator;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Spring's default implementation of the {@link ConfigurableListableBeanFactory}
* and {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
* based on bean definition metadata, extensible through post-processors.
*
* <p>Typical usage is registering all bean definitions first (possibly read
* from a bean definition file), before accessing beans. Bean lookup by name
* is therefore an inexpensive operation in a local bean definition table,
* operating on pre-resolved bean definition metadata objects.
*
* <p>Note that readers for specific bean definition formats are typically
* implemented separately rather than as bean factory subclasses: see for example
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
*
* <p>For an alternative implementation of the
* {@link org.springframework.beans.factory.ListableBeanFactory} interface,
* have a look at {@link StaticListableBeanFactory}, which manages existing
* bean instances rather than creating new ones based on bean definitions.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Sam Brannen
* @author Costin Leau
* @author Chris Beams
* @author Phillip Webb
* @author Stephane Nicoll
* @since 16 April 2001
* @see #registerBeanDefinition
* @see #addBeanPostProcessor
* @see #getBean
* @see #resolveDependency
*/
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Nullable
private static Class<?> javaxInjectProviderClass;
static {
try {
javaxInjectProviderClass =
ClassUtils.forName("jakarta.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
javaxInjectProviderClass = null;
}
}
/** Map from serialized id to factory instance. */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8);
/** Optional id for this factory, for serialization purposes. */
@Nullable
private String serializationId;
/** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true;
/** Whether to allow eager class loading even for lazy-init beans. */
private boolean allowEagerClassLoading = true;
/** Optional OrderComparator for dependency Lists and arrays. */
@Nullable
private Comparator<Object> dependencyComparator;
/** Resolver to use for checking if a bean definition is an autowire candidate. */
private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;
/** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** Map from bean name to merged BeanDefinitionHolder. */
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
/** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
/** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
/** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen;
/**
* Create a new DefaultListableBeanFactory.
*/
public DefaultListableBeanFactory() {
super();
}
/**
* Create a new DefaultListableBeanFactory with the given parent.
* @param parentBeanFactory the parent BeanFactory
*/
public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
/**
* Specify an id for serialization purposes, allowing this BeanFactory to be
* deserialized from this id back into the BeanFactory object, if needed.
*/
public void setSerializationId(@Nullable String serializationId) {
if (serializationId != null) {
serializableFactories.put(serializationId, new WeakReference<>(this));
}
else if (this.serializationId != null) {
serializableFactories.remove(this.serializationId);
}
this.serializationId = serializationId;
}
/**
* Return an id for serialization purposes, if specified, allowing this BeanFactory
* to be deserialized from this id back into the BeanFactory object, if needed.
* @since 4.1.2
*/
@Nullable
public String getSerializationId() {
return this.serializationId;
}
/**
* Set whether it should be allowed to override bean definitions by registering
* a different definition with the same name, automatically replacing the former.
* If not, an exception will be thrown. This also applies to overriding aliases.
* <p>Default is "true".
* @see #registerBeanDefinition
*/
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
/**
* Return whether it should be allowed to override bean definitions by registering
* a different definition with the same name, automatically replacing the former.
* @since 4.1.2
*/
public boolean isAllowBeanDefinitionOverriding() {
return this.allowBeanDefinitionOverriding;
}
/**
* Set whether the factory is allowed to eagerly load bean classes
* even for bean definitions that are marked as "lazy-init".
* <p>Default is "true". Turn this flag off to suppress class loading
* for lazy-init beans unless such a bean is explicitly requested.
* In particular, by-type lookups will then simply ignore bean definitions
* without resolved class name, instead of loading the bean classes on
* demand just to perform a type check.
* @see AbstractBeanDefinition#setLazyInit
*/
public void setAllowEagerClassLoading(boolean allowEagerClassLoading) {
this.allowEagerClassLoading = allowEagerClassLoading;
}
/**
* Return whether the factory is allowed to eagerly load bean classes
* even for bean definitions that are marked as "lazy-init".
* @since 4.1.2
*/
public boolean isAllowEagerClassLoading() {
return this.allowEagerClassLoading;
}
/**
* 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
*/
public void setDependencyComparator(@Nullable Comparator<Object> dependencyComparator) {
this.dependencyComparator = dependencyComparator;
}
/**
* Return the dependency comparator for this BeanFactory (may be {@code null}).
* @since 4.0
*/
@Nullable
public Comparator<Object> getDependencyComparator() {
return this.dependencyComparator;
}
/**
* Set a custom autowire candidate resolver for this BeanFactory to use
* when deciding whether a bean definition should be considered as a
* candidate for autowiring.
*/
public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) {
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
if (autowireCandidateResolver instanceof BeanFactoryAware beanFactoryAware) {
beanFactoryAware.setBeanFactory(this);
}
this.autowireCandidateResolver = autowireCandidateResolver;
}
/**
* Return the autowire candidate resolver for this BeanFactory (never {@code null}).
*/
public AutowireCandidateResolver getAutowireCandidateResolver() {
return this.autowireCandidateResolver;
}
@Override
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
super.copyConfigurationFrom(otherFactory);
if (otherFactory instanceof DefaultListableBeanFactory otherListableFactory) {
this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
this.dependencyComparator = otherListableFactory.dependencyComparator;
// A clone of the AutowireCandidateResolver since it is potentially BeanFactoryAware
setAutowireCandidateResolver(otherListableFactory.getAutowireCandidateResolver().cloneIfNecessary());
// Make resolvable dependencies (e.g. ResourceLoader) available here as well
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
}
}
//---------------------------------------------------------------------
// Implementation of remaining BeanFactory methods
//---------------------------------------------------------------------
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
Assert.notNull(requiredType, "Required type must not be null");
return getBeanProvider(ResolvableType.forRawClass(requiredType), true);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
return getBeanProvider(requiredType, true);
}
//---------------------------------------------------------------------
// Implementation of ListableBeanFactory interface
//---------------------------------------------------------------------
@Override
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
@Override
public int getBeanDefinitionCount() {
return this.beanDefinitionMap.size();
}
@Override
public String[] getBeanDefinitionNames() {
String[] frozenNames = this.frozenBeanDefinitionNames;
if (frozenNames != null) {
return frozenNames.clone();
}
else {
return StringUtils.toStringArray(this.beanDefinitionNames);
}
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
Assert.notNull(requiredType, "Required type must not be null");
return getBeanProvider(ResolvableType.forRawClass(requiredType), allowEagerInit);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
return new BeanObjectProvider<>() {
@Override
public T getObject() throws BeansException {
T resolved = resolveBean(requiredType, null, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return resolved;
}
@Override
public T getObject(Object... args) throws BeansException {
T resolved = resolveBean(requiredType, args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return resolved;
}
@Override
@Nullable
public T getIfAvailable() throws BeansException {
try {
return resolveBean(requiredType, null, false);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope
return null;
}
}
@Override
public void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
T dependency = getIfAvailable();
if (dependency != null) {
try {
dependencyConsumer.accept(dependency);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope, even on scoped proxy invocation
}
}
}
@Override
@Nullable
public T getIfUnique() throws BeansException {
try {
return resolveBean(requiredType, null, true);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope
return null;
}
}
@Override
public void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
T dependency = getIfUnique();
if (dependency != null) {
try {
dependencyConsumer.accept(dependency);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope, even on scoped proxy invocation
}
}
}
@SuppressWarnings("unchecked")
@Override
public Stream<T> stream() {
return Arrays.stream(getBeanNamesForTypedStream(requiredType, allowEagerInit))
.map(name -> (T) getBean(name))
.filter(bean -> !(bean instanceof NullBean));
}
@SuppressWarnings("unchecked")
@Override
public Stream<T> orderedStream() {
String[] beanNames = getBeanNamesForTypedStream(requiredType, allowEagerInit);
if (beanNames.length == 0) {
return Stream.empty();
}
Map<String, T> matchingBeans = CollectionUtils.newLinkedHashMap(beanNames.length);
for (String beanName : beanNames) {
Object beanInstance = getBean(beanName);
if (!(beanInstance instanceof NullBean)) {
matchingBeans.put(beanName, (T) beanInstance);
}
}
Stream<T> stream = matchingBeans.values().stream();
return stream.sorted(adaptOrderComparator(matchingBeans));
}
};
}
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory dlfb) {
return dlfb.resolveBean(requiredType, args, nonUniqueAsNull);
}
else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
}
else {
return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
}
}
return null;
}
private String[] getBeanNamesForTypedStream(ResolvableType requiredType, boolean allowEagerInit) {
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, allowEagerInit);
}
@Override
public String[] getBeanNamesForType(ResolvableType type) {
return getBeanNamesForType(type, true, true);
}
@Override
public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
Class<?> resolved = type.resolve();
if (resolved != null && !type.hasGenerics()) {
return getBeanNamesForType(resolved, includeNonSingletons, allowEagerInit);
}
else {
return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
}
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type) {
return getBeanNamesForType(type, true, true);
}
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
// Check all bean definitions.
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name is not defined as alias for some other bean.
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
boolean matchFound = false;
boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
if (!isFactoryBean) {
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
else {
if (includeNonSingletons || isNonLazyDecorated ||
(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
if (!matchFound) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
}
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably a placeholder: let's ignore it for type matching purposes.
LogMessage message = (ex instanceof CannotLoadBeanClassException ?
LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
logger.trace(message, ex);
// Register exception, in case the bean was accidentally unresolvable.
onSuppressedException(ex);
}
catch (NoSuchBeanDefinitionException ex) {
// Bean definition got removed while we were iterating -> ignore.
}
}
}
// Check manually registered singletons too.
for (String beanName : this.manualSingletonNames) {
try {
// In case of FactoryBean, match object created by FactoryBean.
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
// Match raw bean instance (might be raw FactoryBean).
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Shouldn't happen - probably a result of circular reference resolution...
logger.trace(LogMessage.format(
"Failed to check manually registered singleton with name '%s'", beanName), ex);
}
}
return StringUtils.toStringArray(result);
}
private boolean isSingleton(String beanName, RootBeanDefinition mbd, @Nullable BeanDefinitionHolder dbd) {
return (dbd != null ? mbd.isSingleton() : isSingleton(beanName));
}
/**
* Check whether the specified bean would need to be eagerly initialized
* in order to determine its type.
* @param factoryBeanName a factory-bean reference that the bean definition
* defines a factory method for
* @return whether eager initialization is necessary
*/
private boolean requiresEagerInitForType(@Nullable String factoryBeanName) {
return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName));
}
@Override
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException {
return getBeansOfType(type, true, true);
}
@Override
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBeansOfType(
@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
Map<String, T> result = CollectionUtils.newLinkedHashMap(beanNames.length);
for (String beanName : beanNames) {
try {
Object beanInstance = getBean(beanName);
if (!(beanInstance instanceof NullBean)) {
result.put(beanName, (T) beanInstance);
}
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException bce) {
String exBeanName = bce.getBeanName();
if (exBeanName != null && isCurrentlyInCreation(exBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring match to currently created bean '" + exBeanName + "': " +
ex.getMessage());
}
onSuppressedException(ex);
// Ignore: indicates a circular reference when autowiring constructors.
// We want to find matches other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
return result;
}
@Override
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
List<String> result = new ArrayList<>();
for (String beanName : this.beanDefinitionNames) {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd != null && !bd.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
result.add(beanName);
}
}
for (String beanName : this.manualSingletonNames) {
if (!result.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
result.add(beanName);
}
}
return StringUtils.toStringArray(result);
}
@Override
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
String[] beanNames = getBeanNamesForAnnotation(annotationType);
Map<String, Object> result = CollectionUtils.newLinkedHashMap(beanNames.length);
for (String beanName : beanNames) {
Object beanInstance = getBean(beanName);
if (!(beanInstance instanceof NullBean)) {
result.put(beanName, beanInstance);
}
}
return result;
}
@Override
@Nullable
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException {
return findAnnotationOnBean(beanName, annotationType, true);
}
@Override
@Nullable
public <A extends Annotation> A findAnnotationOnBean(
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
throws NoSuchBeanDefinitionException {
return findMergedAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit)
.synthesize(MergedAnnotation::isPresent).orElse(null);
}
private <A extends Annotation> MergedAnnotation<A> findMergedAnnotationOnBean(
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) {
Class<?> beanType = getType(beanName, allowFactoryBeanInit);
if (beanType != null) {
MergedAnnotation<A> annotation =
MergedAnnotations.from(beanType, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
if (annotation.isPresent()) {
return annotation;
}
}
if (containsBeanDefinition(beanName)) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// Check raw bean class, e.g. in case of a proxy.
if (bd.hasBeanClass() && bd.getFactoryMethodName() == null) {
Class<?> beanClass = bd.getBeanClass();
if (beanClass != beanType) {
MergedAnnotation<A> annotation =
MergedAnnotations.from(beanClass, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
if (annotation.isPresent()) {
return annotation;
}
}
}
// Check annotations declared on factory method, if any.
Method factoryMethod = bd.getResolvedFactoryMethod();
if (factoryMethod != null) {
MergedAnnotation<A> annotation =
MergedAnnotations.from(factoryMethod, SearchStrategy.TYPE_HIERARCHY).get(annotationType);
if (annotation.isPresent()) {
return annotation;
}
}
}
return MergedAnnotation.missing();
}
//---------------------------------------------------------------------
// Implementation of ConfigurableListableBeanFactory interface
//---------------------------------------------------------------------
@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
Assert.notNull(dependencyType, "Dependency type must not be null");
if (autowiredValue != null) {
if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
throw new IllegalArgumentException("Value [" + autowiredValue +
"] does not implement specified dependency type [" + dependencyType.getName() + "]");
}
this.resolvableDependencies.put(dependencyType, autowiredValue);
}
}
@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}
/**
* Determine whether the specified bean definition qualifies as an autowire candidate,
* to be injected into other beans which declare a dependency of matching type.
* @param beanName the name of the bean definition to check
* @param descriptor the descriptor of the dependency to resolve
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
* @return whether the bean should be considered as autowire candidate
*/
protected boolean isAutowireCandidate(
String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
throws NoSuchBeanDefinitionException {
String bdName = BeanFactoryUtils.transformedBeanName(beanName);
if (containsBeanDefinition(bdName)) {
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(bdName), descriptor, resolver);
}
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory dlfb) {
// No bean definition found in this factory -> delegate to parent.
return dlfb.isAutowireCandidate(beanName, descriptor, resolver);
}
else if (parent instanceof ConfigurableListableBeanFactory clfb) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
return clfb.isAutowireCandidate(beanName, descriptor);
}
else {
return true;
}
}
/**
* Determine whether the specified bean definition qualifies as an autowire candidate,
* to be injected into other beans which declare a dependency of matching type.
* @param beanName the name of the bean definition to check
* @param mbd the merged bean definition to check
* @param descriptor the descriptor of the dependency to resolve
* @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm
* @return whether the bean should be considered as autowire candidate
*/
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
String bdName = BeanFactoryUtils.transformedBeanName(beanName);
resolveBeanClass(mbd, bdName);
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
BeanDefinitionHolder holder = (beanName.equals(bdName) ?
this.mergedBeanDefinitionHolders.computeIfAbsent(beanName,
key -> new BeanDefinitionHolder(mbd, beanName, getAliases(bdName))) :
new BeanDefinitionHolder(mbd, beanName, getAliases(bdName)));
return resolver.isAutowireCandidate(holder, descriptor);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
@Override
public Iterator<String> getBeanNamesIterator() {
CompositeIterator<String> iterator = new CompositeIterator<>();
iterator.add(this.beanDefinitionNames.iterator());
iterator.add(this.manualSingletonNames.iterator());
return iterator;
}
@Override
protected void clearMergedBeanDefinition(String beanName) {
super.clearMergedBeanDefinition(beanName);
this.mergedBeanDefinitionHolders.remove(beanName);
}
@Override
public void clearMetadataCache() {
super.clearMetadataCache();
this.mergedBeanDefinitionHolders.clear();
clearByTypeCache();
}
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
@Override
public boolean isConfigurationFrozen() {
return this.configurationFrozen;
}
/**
* Considers all beans as eligible for metadata caching
* if the factory's configuration has been marked as frozen.
* @see #freezeConfiguration()
*/
@Override
protected boolean isBeanEligibleForMetadataCaching(String beanName) {
return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
}
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
}
}
}
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition abd) {
try {
abd.validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (isAlias(beanName)) {
if (!isAllowBeanDefinitionOverriding()) {
String aliasedName = canonicalName(beanName);
if (containsBeanDefinition(aliasedName)) { // alias for existing bean definition
throw new BeanDefinitionOverrideException(
beanName, beanDefinition, getBeanDefinition(aliasedName));
}
else { // alias pointing to non-existing bean definition
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition for bean '" + beanName +
"' since there is already an alias for bean '" + aliasedName + "' bound.");
}
}
else {
removeAlias(beanName);
}
}
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
@Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "'beanName' must not be empty");
BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames);
updatedDefinitions.remove(beanName);
this.beanDefinitionNames = updatedDefinitions;
}
}
else {
// Still in startup registration phase
this.beanDefinitionNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
resetBeanDefinition(beanName);
}
/**
* Reset all bean definition caches for the given bean,
* including the caches of beans that are derived from it.
* <p>Called after an existing bean definition has been replaced or removed,
* triggering {@link #clearMergedBeanDefinition}, {@link #destroySingleton}
* and {@link MergedBeanDefinitionPostProcessor#resetBeanDefinition} on the
* given bean and on all bean definitions that have the given bean as parent.
* @param beanName the name of the bean to reset
* @see #registerBeanDefinition
* @see #removeBeanDefinition
*/
protected void resetBeanDefinition(String beanName) {
// Remove the merged bean definition for the given bean, if already created.
clearMergedBeanDefinition(beanName);
// Remove corresponding bean from singleton cache, if any. Shouldn't usually
// be necessary, rather just meant for overriding a context's default beans
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
destroySingleton(beanName);
// Notify all post-processors that the specified bean definition has been reset.
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.resetBeanDefinition(beanName);
}
// Reset all bean definitions that have the given bean as parent (recursively).
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
// Ensure bd is non-null due to potential concurrent modification of beanDefinitionMap.
if (bd != null && beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}
/**
* Only allows alias overriding if bean definition overriding is allowed.
*/
@Override
protected boolean allowAliasOverriding() {
return isAllowBeanDefinitionOverriding();
}
/**
* Also checks for an alias overriding a bean definition of the same name.
*/
@Override
protected void checkForAliasCircle(String name, String alias) {
super.checkForAliasCircle(name, alias);
if (!isAllowBeanDefinitionOverriding() && containsBeanDefinition(alias)) {
throw new IllegalStateException("Cannot register alias '" + alias +
"' for name '" + name + "': Alias would override bean definition '" + alias + "'");
}
}
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
clearByTypeCache();
}
@Override
public void destroySingletons() {
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
@Override
public void destroySingleton(String beanName) {
super.destroySingleton(beanName);
removeManualSingletonName(beanName);
clearByTypeCache();
}
private void removeManualSingletonName(String beanName) {
updateManualSingletonNames(set -> set.remove(beanName), set -> set.contains(beanName));
}
/**
* Update the factory's internal set of manual singleton names.
* @param action the modification action
* @param condition a precondition for the modification action
* (if this condition does not apply, the action can be skipped)
*/
private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
if (condition.test(this.manualSingletonNames)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
action.accept(updatedSingletons);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
if (condition.test(this.manualSingletonNames)) {
action.accept(this.manualSingletonNames);
}
}
}
/**
* Remove any assumptions about by-type mappings.
*/
private void clearByTypeCache() {
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();
}
//---------------------------------------------------------------------
// Dependency resolution functionality
//---------------------------------------------------------------------
@Override
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
NamedBeanHolder<T> namedBean = resolveNamedBean(ResolvableType.forRawClass(requiredType), null, false);
if (namedBean != null) {
return namedBean;
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof AutowireCapableBeanFactory acbf) {
return acbf.resolveNamedBean(requiredType);
}
throw new NoSuchBeanDefinitionException(requiredType);
}
@SuppressWarnings("unchecked")
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(
ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
String[] candidateNames = getBeanNamesForType(requiredType);
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
if (candidateNames.length == 1) {
return resolveNamedBean(candidateNames[0], requiredType, args);
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (String beanName : candidateNames) {
if (containsSingleton(beanName) && args == null) {
Object beanInstance = getBean(beanName);
candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(beanName, getType(beanName));
}
}
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
if (candidateName == null) {
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null) {
return null;
}
if (beanInstance instanceof Class) {
return resolveNamedBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
}
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(
String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
Object bean = getBean(beanName, null, args);
if (bean instanceof NullBean) {
return null;
}
return new NamedBeanHolder<>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
}
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
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());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
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 (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
if (descriptor instanceof StreamDependencyDescriptor streamDependencyDescriptor) {
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
if (streamDependencyDescriptor.isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
else if (type.isArray()) {
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[] array) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
Arrays.sort(array, comparator);
}
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List<?> list && list.size() > 1) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
list.sort(comparator);
}
}
return result;
}
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
private boolean isRequired(DependencyDescriptor descriptor) {
return getAutowireCandidateResolver().isRequired(descriptor);
}
private boolean indicatesMultipleBeans(Class<?> type) {
return (type.isArray() || (type.isInterface() &&
(Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type))));
}
@Nullable
private Comparator<Object> adaptDependencyComparator(Map<String, ?> matchingBeans) {
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator orderComparator) {
return orderComparator.withSourceProvider(
createFactoryAwareOrderSourceProvider(matchingBeans));
}
else {
return comparator;
}
}
private Comparator<Object> adaptOrderComparator(Map<String, ?> matchingBeans) {
Comparator<Object> dependencyComparator = getDependencyComparator();
OrderComparator comparator = (dependencyComparator instanceof OrderComparator orderComparator ?
orderComparator : OrderComparator.INSTANCE);
return comparator.withSourceProvider(createFactoryAwareOrderSourceProvider(matchingBeans));
}
private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map<String, ?> beans) {
IdentityHashMap<Object, String> instancesToBeanNames = new IdentityHashMap<>();
beans.forEach((beanName, instance) -> instancesToBeanNames.put(instance, beanName));
return new FactoryAwareOrderSourceProvider(instancesToBeanNames);
}
/**
* Find bean instances that match the required type.
* Called during autowiring for the specified bean.
* @param beanName the name of the bean that is about to be wired
* @param requiredType the actual type of bean to look for
* (may be an array component type or collection element type)
* @param descriptor the descriptor of the dependency to resolve
* @return a Map of candidate names and candidate instances that match
* the required type (never {@code null})
* @throws BeansException in case of errors
* @see #autowireByType
* @see #autowireConstructor
*/
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
/**
* Add an entry to the candidate map: a bean instance if available or just the resolved
* type, preventing early bean initialization ahead of primary candidate selection.
*/
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDescriptor) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor streamDescriptor &&
streamDescriptor.isOrdered())) {
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(candidateName, getType(candidateName));
}
}
/**
* Determine the autowire candidate in the given set of beans.
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
* @param candidates a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the autowire candidate, or {@code null} if none found
*/
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
/**
* Determine the primary candidate in the given set of beans.
* @param candidates a Map of candidate names and candidate instances
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the primary candidate, or {@code null} if none found
* @see #isPrimary(String, Object)
*/
@Nullable
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
/**
* Determine the candidate with the highest priority in the given set of beans.
* <p>Based on {@code @jakarta.annotation.Priority}. As defined by the related
* {@link org.springframework.core.Ordered} interface, the lowest value has
* the highest priority.
* @param candidates a Map of candidate names and candidate instances
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority,
* or {@code null} if none found
* @see #getPriority(Object)
*/
@Nullable
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
return highestPriorityBeanName;
}
/**
* Return whether the bean definition for the given bean name has been
* marked as a primary bean.
* @param beanName the name of the bean
* @param beanInstance the corresponding bean instance (can be null)
* @return whether the given bean qualifies as primary
*/
protected boolean isPrimary(String beanName, Object beanInstance) {
String transformedBeanName = transformedBeanName(beanName);
if (containsBeanDefinition(transformedBeanName)) {
return getMergedLocalBeanDefinition(transformedBeanName).isPrimary();
}
return (getParentBeanFactory() instanceof DefaultListableBeanFactory parent &&
parent.isPrimary(transformedBeanName, beanInstance));
}
/**
* Return the priority assigned for the given bean instance by
* the {@code jakarta.annotation.Priority} annotation.
* <p>The default implementation delegates to the specified
* {@link #setDependencyComparator dependency comparator}, checking its
* {@link OrderComparator#getPriority method} if it is an extension of
* Spring's common {@link OrderComparator} - typically, an
* {@link org.springframework.core.annotation.AnnotationAwareOrderComparator}.
* If no such comparator is present, this implementation returns {@code null}.
* @param beanInstance the bean instance to check (can be {@code null})
* @return the priority assigned to that bean or {@code null} if none is set
*/
@Nullable
protected Integer getPriority(Object beanInstance) {
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator orderComparator) {
return orderComparator.getPriority(beanInstance);
}
return null;
}
/**
* Determine whether the given candidate name matches the bean name or the aliases
* stored in this bean definition.
*/
protected boolean matchesBeanName(String beanName, @Nullable String candidateName) {
return (candidateName != null &&
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}
/**
* Determine whether the given beanName/candidateName pair indicates a self reference,
* i.e. whether the candidate points back to the original bean or to a factory method
* on the original bean.
*/
private boolean isSelfReference(@Nullable String beanName, @Nullable String candidateName) {
return (beanName != null && candidateName != null &&
(beanName.equals(candidateName) || (containsBeanDefinition(candidateName) &&
beanName.equals(getMergedLocalBeanDefinition(candidateName).getFactoryBeanName()))));
}
/**
* Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
* for an unresolvable dependency.
*/
private void raiseNoMatchingBeanFound(
Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {
checkBeanNotOfRequiredType(type, descriptor);
throw new NoSuchBeanDefinitionException(resolvableType,
"expected at least 1 bean which qualifies as autowire candidate. " +
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
}
/**
* Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
* i.e. if the target type of the bean would match but an exposed proxy doesn't.
*/
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
for (String beanName : this.beanDefinitionNames) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
Class<?> targetType = mbd.getTargetType();
if (targetType != null && type.isAssignableFrom(targetType) &&
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
// Probably a proxy interfering with target type match -> throw meaningful exception.
Object beanInstance = getSingleton(beanName, false);
Class<?> beanType = (beanInstance != null && beanInstance.getClass() != NullBean.class ?
beanInstance.getClass() : predictBeanType(beanName, mbd));
if (beanType != null && !type.isAssignableFrom(beanType)) {
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// Bean definition got removed while we were iterating -> ignore.
}
}
if (getParentBeanFactory() instanceof DefaultListableBeanFactory parent) {
parent.checkBeanNotOfRequiredType(type, descriptor);
}
}
/**
* Create an {@link Optional} wrapper for the specified dependency.
*/
private Optional<?> createOptionalDependency(
DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {
DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
@Override
public boolean isRequired() {
return false;
}
@Override
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
super.resolveCandidate(beanName, requiredType, beanFactory));
}
};
Object result = doResolveDependency(descriptorToUse, beanName, null, null);
return (result instanceof Optional<?> optional ? optional : Optional.ofNullable(result));
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(ObjectUtils.identityToString(this));
sb.append(": defining beans [");
sb.append(StringUtils.collectionToCommaDelimitedString(this.beanDefinitionNames));
sb.append("]; ");
BeanFactory parent = getParentBeanFactory();
if (parent == null) {
sb.append("root of factory hierarchy");
}
else {
sb.append("parent: ").append(ObjectUtils.identityToString(parent));
}
return sb.toString();
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
@Serial
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " +
"just a SerializedBeanFactoryReference is");
}
@Serial
protected Object writeReplace() throws ObjectStreamException {
if (this.serializationId != null) {
return new SerializedBeanFactoryReference(this.serializationId);
}
else {
throw new NotSerializableException("DefaultListableBeanFactory has no serialization id");
}
}
/**
* Minimal id reference to the factory.
* Resolved to the actual factory instance on deserialization.
*/
private static class SerializedBeanFactoryReference implements Serializable {
private final String id;
public SerializedBeanFactoryReference(String id) {
this.id = id;
}
private Object readResolve() {
Reference<?> ref = serializableFactories.get(this.id);
if (ref != null) {
Object result = ref.get();
if (result != null) {
return result;
}
}
// Lenient fallback: dummy factory in case of original factory not found...
DefaultListableBeanFactory dummyFactory = new DefaultListableBeanFactory();
dummyFactory.serializationId = this.id;
return dummyFactory;
}
}
/**
* A dependency descriptor marker for nested elements.
*/
private static class NestedDependencyDescriptor extends DependencyDescriptor {
public NestedDependencyDescriptor(DependencyDescriptor original) {
super(original);
increaseNestingLevel();
}
}
/**
* A dependency descriptor for a multi-element declaration with nested elements.
*/
private static class MultiElementDescriptor extends NestedDependencyDescriptor {
public MultiElementDescriptor(DependencyDescriptor original) {
super(original);
}
}
/**
* A dependency descriptor marker for stream access to multiple elements.
*/
private static class StreamDependencyDescriptor extends DependencyDescriptor {
private final boolean ordered;
public StreamDependencyDescriptor(DependencyDescriptor original, boolean ordered) {
super(original);
this.ordered = ordered;
}
public boolean isOrdered() {
return this.ordered;
}
}
private interface BeanObjectProvider<T> extends ObjectProvider<T>, Serializable {
}
/**
* Serializable ObjectFactory/ObjectProvider for lazy resolution of a dependency.
*/
private class DependencyObjectProvider implements BeanObjectProvider<Object> {
private final DependencyDescriptor descriptor;
private final boolean optional;
@Nullable
private final String beanName;
public DependencyObjectProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
this.descriptor = new NestedDependencyDescriptor(descriptor);
this.optional = (this.descriptor.getDependencyType() == Optional.class);
this.beanName = beanName;
}
@Override
public Object getObject() throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
Object result = doResolveDependency(this.descriptor, this.beanName, null, null);
if (result == null) {
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
}
return result;
}
}
@Override
public Object getObject(final Object... args) throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName, args);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
@Override
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
return beanFactory.getBean(beanName, args);
}
};
Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
if (result == null) {
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
}
return result;
}
}
@Override
@Nullable
public Object getIfAvailable() throws BeansException {
try {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
@Override
public boolean isRequired() {
return false;
}
};
return doResolveDependency(descriptorToUse, this.beanName, null, null);
}
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope
return null;
}
}
@Override
public void ifAvailable(Consumer<Object> dependencyConsumer) throws BeansException {
Object dependency = getIfAvailable();
if (dependency != null) {
try {
dependencyConsumer.accept(dependency);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope, even on scoped proxy invocation
}
}
}
@Override
@Nullable
public Object getIfUnique() throws BeansException {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
@Override
public boolean isRequired() {
return false;
}
@Override
@Nullable
public Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) {
return null;
}
};
try {
if (this.optional) {
return createOptionalDependency(descriptorToUse, this.beanName);
}
else {
return doResolveDependency(descriptorToUse, this.beanName, null, null);
}
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope
return null;
}
}
@Override
public void ifUnique(Consumer<Object> dependencyConsumer) throws BeansException {
Object dependency = getIfUnique();
if (dependency != null) {
try {
dependencyConsumer.accept(dependency);
}
catch (ScopeNotActiveException ex) {
// Ignore resolved bean in non-active scope, even on scoped proxy invocation
}
}
}
@Nullable
protected Object getValue() throws BeansException {
if (this.optional) {
return createOptionalDependency(this.descriptor, this.beanName);
}
else {
return doResolveDependency(this.descriptor, this.beanName, null, null);
}
}
@Override
public Stream<Object> stream() {
return resolveStream(false);
}
@Override
public Stream<Object> orderedStream() {
return resolveStream(true);
}
@SuppressWarnings("unchecked")
private Stream<Object> resolveStream(boolean ordered) {
DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);
Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));
}
}
/**
* Separate inner class for avoiding a hard dependency on the {@code jakarta.inject} API.
* Actual {@code jakarta.inject.Provider} implementation is nested here in order to make it
* invisible for Graal's introspection of DefaultListableBeanFactory's nested classes.
*/
private class Jsr330Factory implements Serializable {
public Object createDependencyProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
return new Jsr330Provider(descriptor, beanName);
}
private class Jsr330Provider extends DependencyObjectProvider implements Provider<Object> {
public Jsr330Provider(DependencyDescriptor descriptor, @Nullable String beanName) {
super(descriptor, beanName);
}
@Override
@Nullable
public Object get() throws BeansException {
return getValue();
}
}
}
/**
* An {@link org.springframework.core.OrderComparator.OrderSourceProvider} implementation
* that is aware of the bean metadata of the instances to sort.
* <p>Lookup for the method factory of an instance to sort, if any, and let the
* comparator retrieve the {@link org.springframework.core.annotation.Order}
* value defined on it. This essentially allows for the following construct:
*/
private class FactoryAwareOrderSourceProvider implements OrderComparator.OrderSourceProvider {
private final Map<Object, String> instancesToBeanNames;
public FactoryAwareOrderSourceProvider(Map<Object, String> instancesToBeanNames) {
this.instancesToBeanNames = instancesToBeanNames;
}
@Override
@Nullable
public Object getOrderSource(Object obj) {
String beanName = this.instancesToBeanNames.get(obj);
if (beanName == null || !containsBeanDefinition(beanName)) {
return null;
}
RootBeanDefinition beanDefinition = getMergedLocalBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray();
}
}
}
相关信息
相关文章
spring AbstractAutowireCapableBeanFactory 源码
spring AbstractBeanDefinition 源码
spring AbstractBeanDefinitionReader 源码
spring AutowireCandidateQualifier 源码
spring AutowireCandidateResolver 源码
spring BeanDefinitionBuilder 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦