All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.beans.factory.support.DefaultListableBeanFactory Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * 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.
 * 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.Serializable;
import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
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.LinkedHashMap;
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 javax.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.FactoryBean;
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.BeanPostProcessor;
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.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
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.
 *
 * 

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. * *

Note that readers for specific bean definition formats are typically * implemented separately rather than as bean factory subclasses: * see for example {@link PropertiesBeanDefinitionReader} and * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}. * *

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("javax.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> 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 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, Object> resolvableDependencies = new ConcurrentHashMap<>(16); /** Map of bean definition objects, keyed by bean name. */ private final Map beanDefinitionMap = new ConcurrentHashMap<>(256); /** Map from bean name to merged BeanDefinitionHolder. */ private final Map mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256); /** Map of singleton and non-singleton bean names, keyed by dependency type. */ private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64); /** Map of singleton-only bean names, keyed by dependency type. */ private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64); /** List of bean definition names, in registration order. */ private volatile List beanDefinitionNames = new ArrayList<>(256); /** List of names of manually registered singletons, in registration order. */ private volatile Set 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 = false; /** * 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. *

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". *

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 dependencyComparator) { this.dependencyComparator = dependencyComparator; } /** * Return the dependency comparator for this BeanFactory (may be {@code null}. * @since 4.0 */ @Nullable public Comparator 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(final AutowireCandidateResolver autowireCandidateResolver) { Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null"); if (autowireCandidateResolver instanceof BeanFactoryAware) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this); return null; }, getAccessControlContext()); } else { ((BeanFactoryAware) autowireCandidateResolver).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) { DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory; 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 getBean(Class requiredType) throws BeansException { return getBean(requiredType, (Object[]) null); } @SuppressWarnings("unchecked") @Override public T getBean(Class 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 ObjectProvider getBeanProvider(Class requiredType) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); return getBeanProvider(ResolvableType.forRawClass(requiredType)); } @SuppressWarnings("unchecked") @Override public ObjectProvider getBeanProvider(ResolvableType requiredType) { 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 { return resolveBean(requiredType, null, false); } @Override @Nullable public T getIfUnique() throws BeansException { return resolveBean(requiredType, null, true); } @Override public Stream stream() { return Arrays.stream(getBeanNamesForTypedStream(requiredType)) .map(name -> (T) getBean(name)) .filter(bean -> !(bean instanceof NullBean)); } @Override public Stream orderedStream() { String[] beanNames = getBeanNamesForTypedStream(requiredType); if (beanNames.length == 0) { return Stream.empty(); } Map matchingBeans = new LinkedHashMap<>(beanNames.length); for (String beanName : beanNames) { Object beanInstance = getBean(beanName); if (!(beanInstance instanceof NullBean)) { matchingBeans.put(beanName, (T) beanInstance); } } Stream stream = matchingBeans.values().stream(); return stream.sorted(adaptOrderComparator(matchingBeans)); } }; } @Nullable private T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) { NamedBeanHolder namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull); if (namedBean != null) { return namedBean.getBeanInstance(); } BeanFactory parent = getParentBeanFactory(); if (parent instanceof DefaultListableBeanFactory) { return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull); } else if (parent != null) { ObjectProvider 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) { return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType); } //--------------------------------------------------------------------- // 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 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, 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 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; 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); onSuppressedException(ex); } } } // 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 Map getBeansOfType(@Nullable Class type) throws BeansException { return getBeansOfType(type, true, true); } @Override @SuppressWarnings("unchecked") public Map getBeansOfType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException { String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit); Map result = new LinkedHashMap<>(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) { BeanCreationException bce = (BeanCreationException) rootCause; 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 annotationType) { List result = new ArrayList<>(); for (String beanName : this.beanDefinitionNames) { BeanDefinition beanDefinition = getBeanDefinition(beanName); if (!beanDefinition.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 getBeansWithAnnotation(Class annotationType) { String[] beanNames = getBeanNamesForAnnotation(annotationType); Map result = new LinkedHashMap<>(beanNames.length); for (String beanName : beanNames) { Object beanInstance = getBean(beanName); if (!(beanInstance instanceof NullBean)) { result.put(beanName, beanInstance); } } return result; } @Override @Nullable public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { return findMergedAnnotationOnBean(beanName, annotationType) .synthesize(MergedAnnotation::isPresent).orElse(null); } private MergedAnnotation findMergedAnnotationOnBean( String beanName, Class annotationType) { Class beanType = getType(beanName); if (beanType != null) { MergedAnnotation 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()) { Class beanClass = bd.getBeanClass(); if (beanClass != beanType) { MergedAnnotation 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 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 beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); if (containsBeanDefinition(beanDefinitionName)) { return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver); } else if (containsSingleton(beanName)) { return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver); } BeanFactory parent = getParentBeanFactory(); if (parent instanceof DefaultListableBeanFactory) { // No bean definition found in this factory -> delegate to parent. return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver); } else if (parent instanceof ConfigurableListableBeanFactory) { // If no DefaultListableBeanFactory, can't pass the resolver along. return ((ConfigurableListableBeanFactory) parent).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 beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); resolveBeanClass(mbd, beanDefinitionName); if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) { new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd); } BeanDefinitionHolder holder = (beanName.equals(beanDefinitionName) ? this.mergedBeanDefinitionHolders.computeIfAbsent(beanName, key -> new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName))) : new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName))); 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 getBeanNamesIterator() { CompositeIterator 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 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 FactoryBean) { final FactoryBean factory = (FactoryBean) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()); } if (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) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } } //--------------------------------------------------------------------- // 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) { try { ((AbstractBeanDefinition) beanDefinition).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 (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List 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 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. *

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 (BeanPostProcessor processor : getBeanPostProcessors()) { if (processor instanceof MergedBeanDefinitionPostProcessor) { ((MergedBeanDefinitionPostProcessor) 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 the 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(); } @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> action, Predicate> condition) { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { if (condition.test(this.manualSingletonNames)) { Set 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 NamedBeanHolder resolveNamedBean(Class requiredType) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); NamedBeanHolder namedBean = resolveNamedBean(ResolvableType.forRawClass(requiredType), null, false); if (namedBean != null) { return namedBean; } BeanFactory parent = getParentBeanFactory(); if (parent instanceof AutowireCapableBeanFactory) { return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType); } throw new NoSuchBeanDefinitionException(requiredType); } @SuppressWarnings("unchecked") @Nullable private NamedBeanHolder 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 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) { String beanName = candidateNames[0]; return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args)); } else if (candidateNames.length > 1) { Map candidates = new LinkedHashMap<>(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 || beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType.toClass(), args); } return new NamedBeanHolder<>(candidateName, (T) beanInstance); } if (!nonUniqueAsNull) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); } } return null; } @Override @Nullable public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set 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 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 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 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 autowiredBeanNames, @Nullable TypeConverter typeConverter) { final Class type = descriptor.getDependencyType(); if (descriptor instanceof StreamDependencyDescriptor) { Map matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } Stream stream = matchingBeans.keySet().stream() .map(name -> descriptor.resolveCandidate(name, type, this)) .filter(bean -> !(bean instanceof NullBean)); if (((StreamDependencyDescriptor) descriptor).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 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[]) { Comparator comparator = adaptDependencyComparator(matchingBeans); if (comparator != null) { Arrays.sort((Object[]) result, comparator); } } return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class elementType = descriptor.getResolvableType().asCollection().resolveGeneric(); if (elementType == null) { return null; } Map 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) { if (((List) result).size() > 1) { Comparator comparator = adaptDependencyComparator(matchingBeans); if (comparator != null) { ((List) result).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 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 adaptDependencyComparator(Map matchingBeans) { Comparator comparator = getDependencyComparator(); if (comparator instanceof OrderComparator) { return ((OrderComparator) comparator).withSourceProvider( createFactoryAwareOrderSourceProvider(matchingBeans)); } else { return comparator; } } private Comparator adaptOrderComparator(Map matchingBeans) { Comparator dependencyComparator = getDependencyComparator(); OrderComparator comparator = (dependencyComparator instanceof OrderComparator ? (OrderComparator) dependencyComparator : OrderComparator.INSTANCE); return comparator.withSourceProvider(createFactoryAwareOrderSourceProvider(matchingBeans)); } private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map beans) { IdentityHashMap 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 findAutowireCandidates( @Nullable String beanName, Class requiredType, DependencyDescriptor descriptor) { String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map result = new LinkedHashMap<>(candidateNames.length); for (Map.Entry, 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 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 && ((StreamDependencyDescriptor) descriptor).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. *

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 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 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 candidates, Class requiredType) { String primaryBeanName = null; for (Map.Entry 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. *

Based on {@code @javax.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 candidates, Class requiredType) { String highestPriorityBeanName = null; Integer highestPriority = null; for (Map.Entry 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(); } BeanFactory parent = getParentBeanFactory(); return (parent instanceof DefaultListableBeanFactory && ((DefaultListableBeanFactory) parent).isPrimary(transformedBeanName, beanInstance)); } /** * Return the priority assigned for the given bean instance by * the {@code javax.annotation.Priority} annotation. *

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 comparator = getDependencyComparator(); if (comparator instanceof OrderComparator) { return ((OrderComparator) comparator).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) { 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); } } } BeanFactory parent = getParentBeanFactory(); if (parent instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) 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) result : 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 //--------------------------------------------------------------------- private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " + "just a SerializedBeanFactoryReference is"); } 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 extends ObjectProvider, Serializable { } /** * Serializable ObjectFactory/ObjectProvider for lazy resolution of a dependency. */ private class DependencyObjectProvider implements BeanObjectProvider { 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 { 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); } } @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 matchingBeans) { return null; } }; if (this.optional) { return createOptionalDependency(descriptorToUse, this.beanName); } else { return doResolveDependency(descriptorToUse, this.beanName, null, null); } } @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 stream() { return resolveStream(false); } @Override public Stream orderedStream() { return resolveStream(true); } @SuppressWarnings("unchecked") private Stream resolveStream(boolean ordered) { DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered); Object result = doResolveDependency(descriptorToUse, this.beanName, null, null); return (result instanceof Stream ? (Stream) result : Stream.of(result)); } } /** * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API. * Actual {@code javax.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 { 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. *

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 instancesToBeanNames; public FactoryAwareOrderSourceProvider(Map 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 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(); } } }