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.13
Show newest version
/*
 * Copyright 2002-2019 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.Collections;
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 javax.inject.Provider;

import org.springframework.beans.BeanUtils;
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.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.AnnotationUtils;
import org.springframework.lang.UsesJava8;
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 { private static Class javaUtilOptionalClass = null; private static Class javaxInjectProviderClass = null; static { try { javaUtilOptionalClass = ClassUtils.forName("java.util.Optional", DefaultListableBeanFactory.class.getClassLoader()); } catch (ClassNotFoundException ex) { // Java 8 not available - Optional references simply not supported then. } try { javaxInjectProviderClass = ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader()); } catch (ClassNotFoundException ex) { // JSR-330 API not available - Provider interface simply not supported then. } } /** Map from serialized id to factory instance */ private static final Map> serializableFactories = new ConcurrentHashMap>(8); /** Optional id for this factory, for serialization purposes */ 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 */ private Comparator dependencyComparator; /** Resolver to use for checking if a bean definition is an autowire candidate */ private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); /** Map from dependency type to corresponding autowired value */ private final Map, Object> resolvableDependencies = new ConcurrentHashMap, Object>(16); /** Map of bean definition objects, keyed by bean name */ private final Map beanDefinitionMap = new ConcurrentHashMap(256); /** Map of singleton and non-singleton bean names, keyed by dependency type */ private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap, String[]>(64); /** Map of singleton-only bean names, keyed by dependency type */ private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap, String[]>(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 */ 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(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(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 */ 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(Comparator dependencyComparator) { this.dependencyComparator = dependencyComparator; } /** * Return the dependency comparator for this BeanFactory (may be {@code null}. * @since 4.0 */ 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(new PrivilegedAction() { @Override public Object run() { ((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(BeanUtils.instantiateClass(getAutowireCandidateResolver().getClass())); // 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); } @Override public T getBean(Class requiredType, Object... args) throws BeansException { NamedBeanHolder namedBean = resolveNamedBean(requiredType, args); if (namedBean != null) { return namedBean.getBeanInstance(); } BeanFactory parent = getParentBeanFactory(); if (parent != null) { return parent.getBean(requiredType, args); } throw new NoSuchBeanDefinitionException(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 doGetBeanNamesForType(type, true, true); } @Override public String[] getBeanNamesForType(Class type) { return getBeanNamesForType(type, true, true); } @Override public String[] getBeanNamesForType(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()))) { // In case of FactoryBean, match object created by FactoryBean. boolean isFactoryBean = isFactoryBean(beanName, mbd); BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); boolean matchFound = (allowEagerInit || !isFactoryBean || (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) && (includeNonSingletons || (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) && isTypeMatch(beanName, type); if (!matchFound && isFactoryBean) { // In case of FactoryBean, try to match FactoryBean instance itself next. beanName = FACTORY_BEAN_PREFIX + beanName; matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type); } if (matchFound) { result.add(beanName); } } } catch (CannotLoadBeanClassException ex) { if (allowEagerInit) { throw ex; } // Probably a class name with a placeholder: let's ignore it for type matching purposes. if (logger.isDebugEnabled()) { logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex); } onSuppressedException(ex); } catch (BeanDefinitionStoreException ex) { if (allowEagerInit) { throw ex; } // Probably some metadata with a placeholder: let's ignore it for type matching purposes. if (logger.isDebugEnabled()) { logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", 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... if (logger.isDebugEnabled()) { logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex); } } } return StringUtils.toStringArray(result); } /** * 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(String factoryBeanName) { return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName)); } @Override public Map getBeansOfType(Class type) throws BeansException { return getBeansOfType(type, true, true); } @Override public Map getBeansOfType(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 { result.put(beanName, getBean(beanName, type)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Ignoring match to currently created bean '" + beanName + "': " + 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) { result.put(beanName, getBean(beanName)); } return result; } @Override public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { A ann = null; Class beanType = getType(beanName); if (beanType != null) { ann = AnnotationUtils.findAnnotation(beanType, annotationType); } if (ann == null && containsBeanDefinition(beanName)) { // Check raw bean class, e.g. in case of a proxy. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (bd.hasBeanClass()) { Class beanClass = bd.getBeanClass(); if (beanClass != beanType) { ann = AnnotationUtils.findAnnotation(beanClass, annotationType); } } } return ann; } //--------------------------------------------------------------------- // Implementation of ConfigurableListableBeanFactory interface //--------------------------------------------------------------------- @Override public void registerResolvableDependency(Class dependencyType, 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) { boolean resolve; synchronized (mbd.constructorArgumentLock) { resolve = (mbd.resolvedConstructorOrFactoryMethod == null); } if (resolve) { new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd); } } return resolver.isAutowireCandidate( new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), 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 public void clearMetadataCache() { super.clearMetadataCache(); 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.isDebugEnabled()) { logger.debug("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)) { final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction() { @Override public Boolean run() { return ((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(new PrivilegedAction() { @Override public Object run() { 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 BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + existingDefinition + "] bound."); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isWarnEnabled()) { logger.warn("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.isInfoEnabled()) { logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isDebugEnabled()) { logger.debug("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; if (this.manualSingletonNames.contains(beanName)) { Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } } @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. * @param beanName the name of the bean to reset */ 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); // 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); if (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); if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { if (!this.beanDefinitionMap.containsKey(beanName)) { Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames.size() + 1); updatedSingletons.addAll(this.manualSingletonNames); updatedSingletons.add(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase if (!this.beanDefinitionMap.containsKey(beanName)) { this.manualSingletonNames.add(beanName); } } clearByTypeCache(); } @Override public void destroySingleton(String beanName) { super.destroySingleton(beanName); this.manualSingletonNames.remove(beanName); clearByTypeCache(); } @Override public void destroySingletons() { super.destroySingletons(); this.manualSingletonNames.clear(); clearByTypeCache(); } /** * 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 { NamedBeanHolder namedBean = resolveNamedBean(requiredType, (Object[]) null); if (namedBean != null) { return namedBean; } BeanFactory parent = getParentBeanFactory(); if (parent instanceof AutowireCapableBeanFactory) { return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType); } throw new NoSuchBeanDefinitionException(requiredType); } @SuppressWarnings("unchecked") private NamedBeanHolder resolveNamedBean(Class requiredType, Object... args) 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, getBean(beanName, requiredType, args)); } else if (candidateNames.length > 1) { Map candidates = new LinkedHashMap(candidateNames.length); for (String beanName : candidateNames) { if (containsSingleton(beanName)) { candidates.put(beanName, getBean(beanName, requiredType, args)); } else { candidates.put(beanName, getType(beanName)); } } String candidateName = determinePrimaryCandidate(candidates, requiredType); if (candidateName == null) { candidateName = determineHighestPriorityCandidate(candidates, requiredType); } if (candidateName != null) { Object beanInstance = candidates.get(candidateName); if (beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType, args); } return new NamedBeanHolder(candidateName, (T) beanInstance); } throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); } return null; } @Override public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (javaUtilOptionalClass == descriptor.getDependencyType()) { return new OptionalDependencyFactory().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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName); } else { Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } } public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set autowiredBeanNames, 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()); 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(type, 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); } return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate); } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } } private Object resolveMultipleBeans(DependencyDescriptor descriptor, String beanName, Set autowiredBeanNames, TypeConverter typeConverter) { Class type = descriptor.getDependencyType(); if (type.isArray()) { Class componentType = type.getComponentType(); ResolvableType resolvableType = descriptor.getResolvableType(); Class resolvedArrayType = resolvableType.resolve(); if (resolvedArrayType != null && resolvedArrayType != type) { type = resolvedArrayType; 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(), type); if (getDependencyComparator() != null && result instanceof Object[]) { Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans)); } 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 (getDependencyComparator() != null && result instanceof List) { Collections.sort((List) result, adaptDependencyComparator(matchingBeans)); } 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) { AutowireCandidateResolver resolver = getAutowireCandidateResolver(); return (resolver instanceof SimpleAutowireCandidateResolver ? ((SimpleAutowireCandidateResolver) resolver).isRequired(descriptor) : descriptor.isRequired()); } private boolean indicatesMultipleBeans(Class type) { return (type.isArray() || (type.isInterface() && (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)))); } private Comparator adaptDependencyComparator(Map matchingBeans) { Comparator comparator = getDependencyComparator(); if (comparator instanceof OrderComparator) { return ((OrderComparator) comparator).withSourceProvider( createFactoryAwareOrderSourceProvider(matchingBeans)); } else { return comparator; } } private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map beans) { IdentityHashMap instancesToBeanNames = new IdentityHashMap(); for (Map.Entry entry : beans.entrySet()) { instancesToBeanNames.put(entry.getValue(), entry.getKey()); } 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( String beanName, Class requiredType, DependencyDescriptor descriptor) { String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map result = new LinkedHashMap(candidateNames.length); for (Class autowiringType : this.resolvableDependencies.keySet()) { if (autowiringType.isAssignableFrom(requiredType)) { Object autowiringValue = this.resolvableDependencies.get(autowiringType); 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() && !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)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty()) { // 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 || containsSingleton(candidateName)) { candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this)); } 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 */ 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) */ 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) */ 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(); 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) { if (containsBeanDefinition(beanName)) { return getMergedLocalBeanDefinition(beanName).isPrimary(); } BeanFactory parent = getParentBeanFactory(); return (parent instanceof DefaultListableBeanFactory && ((DefaultListableBeanFactory) parent).isPrimary(beanName, 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 */ 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, 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(String beanName, 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() : predictBeanType(beanName, mbd)); if (!type.isAssignableFrom((beanType))) { throw new BeanNotOfRequiredTypeException(beanName, type, beanType); } } } BeanFactory parent = getParentBeanFactory(); if (parent instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor); } } @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); } } /** * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API. */ @UsesJava8 private class OptionalDependencyFactory { public Object createOptionalDependency(DependencyDescriptor descriptor, 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, requiredType, args) : super.resolveCandidate(beanName, requiredType, beanFactory)); } }; Object result = doResolveDependency(descriptorToUse, beanName, null, null); return (result instanceof Optional ? (Optional) result : Optional.ofNullable(result)); } } /** * Serializable ObjectFactory/ObjectProvider for lazy resolution of a dependency. */ private class DependencyObjectProvider implements ObjectProvider, Serializable { private final DependencyDescriptor descriptor; private final boolean optional; private final String beanName; public DependencyObjectProvider(DependencyDescriptor descriptor, String beanName) { this.descriptor = new NestedDependencyDescriptor(descriptor); this.optional = (this.descriptor.getDependencyType() == javaUtilOptionalClass); this.beanName = beanName; } @Override public Object getObject() throws BeansException { if (this.optional) { return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName); } else { return doResolveDependency(this.descriptor, this.beanName, null, null); } } @Override public Object getObject(final Object... args) throws BeansException { if (this.optional) { return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName, args); } else { DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) { @Override public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory) { return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args); } }; return doResolveDependency(descriptorToUse, this.beanName, null, null); } } @Override public Object getIfAvailable() throws BeansException { if (this.optional) { return new OptionalDependencyFactory().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 public Object getIfUnique() throws BeansException { DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) { @Override public boolean isRequired() { return false; } @Override public Object resolveNotUnique(Class type, Map matchingBeans) { return null; } }; if (this.optional) { return new OptionalDependencyFactory().createOptionalDependency(descriptorToUse, this.beanName); } else { return doResolveDependency(descriptorToUse, this.beanName, null, null); } } } /** * A {@code javax.inject.Provider} implementation for lazy resolution of a dependency. */ private class Jsr330DependencyProvider extends DependencyObjectProvider implements Provider { public Jsr330DependencyProvider(DependencyDescriptor descriptor, String beanName) { super(descriptor, beanName); } @Override public Object get() throws BeansException { return getObject(); } } /** * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API. */ private class Jsr330ProviderFactory { public Object createDependencyProvider(DependencyDescriptor descriptor, String beanName) { return new Jsr330DependencyProvider(descriptor, beanName); } } /** * 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 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(); } } }