一:缓存中获取单例bean
前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /** * Internal marker for a null singleton object: * used as marker value for concurrent Maps (which don‘t support null values). */ protected static final Object NULL_OBJECT = new Object(); /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); /** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256); /** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16); /** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); /** Set of registered singletons, containing the bean names in registration order */ private final Set<String> registeredSingletons = new LinkedHashSet<String>(256); /** Names of beans that are currently in creation */ private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); /** Names of beans currently excluded from in creation checks */ private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); /** List of suppressed Exceptions, available for associating related causes */ private Set<Exception> suppressedExceptions; /** Flag that indicates whether we‘re currently within destroySingletons */ private boolean singletonsCurrentlyInDestruction = false; /** Disposable bean instances: bean name --> disposable instance */ private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>(); /** Map between containing bean names: bean name --> Set of bean names that the bean contains */ private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16); /** Map between dependent bean names: bean name --> Set of dependent bean names */ private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64); /** Map between depending bean names: bean name --> Set of bean names for the bean‘s dependencies */ private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64); @Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "‘beanName‘ must not be null"); synchronized (this.singletonObjects) { Object oldObject = this.singletonObjects.get(beanName); if (oldObject != null) { throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name ‘" + beanName + "‘: there is already object [" + oldObject + "] bound"); } addSingleton(beanName, singletonObject); } } /** * Add the given singleton object to the singleton cache of this factory. * <p>To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } /** * Add the given singleton factory for building the specified singleton * if necessary. * <p>To be called for eager registration of singletons, e.g. to be able to * resolve circular references. * @param beanName the name of the bean * @param singletonFactory the factory for the singleton object */ protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } } @Override public Object getSingleton(String beanName) { return getSingleton(beanName, true); } /** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } /** * Return the (raw) singleton object registered under the given name, * creating and registering a new one if none registered yet. * @param beanName the name of the bean * @param singletonFactory the ObjectFactory to lazily create the singleton * with, if necessary * @return the registered singleton object */ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "‘beanName‘ must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean ‘" + beanName + "‘"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } } /** * Register an Exception that happened to get suppressed during the creation of a * singleton bean instance, e.g. a temporary circular reference resolution problem. * @param ex the Exception to register */ protected void onSuppressedException(Exception ex) { synchronized (this.singletonObjects) { if (this.suppressedExceptions != null) { this.suppressedExceptions.add(ex); } } } /** * Remove the bean with the given name from the singleton cache of this factory, * to be able to clean up eager registration of a singleton if creation failed. * @param beanName the name of the bean * @see #getSingletonMutex() */ protected void removeSingleton(String beanName) { synchronized (this.singletonObjects) { this.singletonObjects.remove(beanName); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.remove(beanName); } } @Override public boolean containsSingleton(String beanName) { return this.singletonObjects.containsKey(beanName); } @Override public String[] getSingletonNames() { synchronized (this.singletonObjects) { return StringUtils.toStringArray(this.registeredSingletons); } } @Override public int getSingletonCount() { synchronized (this.singletonObjects) { return this.registeredSingletons.size(); } } public void setCurrentlyInCreation(String beanName, boolean inCreation) { Assert.notNull(beanName, "Bean name must not be null"); if (!inCreation) { this.inCreationCheckExclusions.add(beanName); } else { this.inCreationCheckExclusions.remove(beanName); } } public boolean isCurrentlyInCreation(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName)); } protected boolean isActuallyInCreation(String beanName) { return isSingletonCurrentlyInCreation(beanName); } /** * Return whether the specified singleton bean is currently in creation * (within the entire factory). * @param beanName the name of the bean */ public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); } /** * Callback before singleton creation. * <p>The default implementation register the singleton as currently in creation. * @param beanName the name of the singleton about to be created * @see #isSingletonCurrentlyInCreation */ protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } /** * Callback after singleton creation. * <p>The default implementation marks the singleton as not in creation anymore. * @param beanName the name of the singleton that has been created * @see #isSingletonCurrentlyInCreation */ protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton ‘" + beanName + "‘ isn‘t currently in creation"); } } /** * Add the given bean to the list of disposable beans in this registry. * <p>Disposable beans usually correspond to registered singletons, * matching the bean name but potentially being a different instance * (for example, a DisposableBean adapter for a singleton that does not * naturally implement Spring‘s DisposableBean interface). * @param beanName the name of the bean * @param bean the bean instance */ public void registerDisposableBean(String beanName, DisposableBean bean) { synchronized (this.disposableBeans) { this.disposableBeans.put(beanName, bean); } } /** * Register a containment relationship between two beans, * e.g. between an inner bean and its containing outer bean. * <p>Also registers the containing bean as dependent on the contained bean * in terms of destruction order. * @param containedBeanName the name of the contained (inner) bean * @param containingBeanName the name of the containing (outer) bean * @see #registerDependentBean */ public void registerContainedBean(String containedBeanName, String containingBeanName) { // A quick check for an existing entry upfront, avoiding synchronization... Set<String> containedBeans = this.containedBeanMap.get(containingBeanName); if (containedBeans != null && containedBeans.contains(containedBeanName)) { return; } // No entry yet -> fully synchronized manipulation of the containedBeans Set synchronized (this.containedBeanMap) { containedBeans = this.containedBeanMap.get(containingBeanName); if (containedBeans == null) { containedBeans = new LinkedHashSet<String>(8); this.containedBeanMap.put(containingBeanName, containedBeans); } containedBeans.add(containedBeanName); } registerDependentBean(containedBeanName, containingBeanName); } /** * Register a dependent bean for the given bean, * to be destroyed before the given bean is destroyed. * @param beanName the name of the bean * @param dependentBeanName the name of the dependent bean */ public void registerDependentBean(String beanName, String dependentBeanName) { // A quick check for an existing entry upfront, avoiding synchronization... String canonicalName = canonicalName(beanName); Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) { return; } // No entry yet -> fully synchronized manipulation of the dependentBeans Set synchronized (this.dependentBeanMap) { dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { dependentBeans = new LinkedHashSet<String>(8); this.dependentBeanMap.put(canonicalName, dependentBeans); } dependentBeans.add(dependentBeanName); } synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName); if (dependenciesForBean == null) { dependenciesForBean = new LinkedHashSet<String>(8); this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean); } dependenciesForBean.add(canonicalName); } } /** * Determine whether the specified dependent bean has been registered as * dependent on the given bean or on any of its transitive dependencies. * @param beanName the name of the bean to check * @param dependentBeanName the name of the dependent bean * @since 4.0 */ protected boolean isDependent(String beanName, String dependentBeanName) { return isDependent(beanName, dependentBeanName, null); } private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) { if (alreadySeen != null && alreadySeen.contains(beanName)) { return false; } String canonicalName = canonicalName(beanName); Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { return false; } if (dependentBeans.contains(dependentBeanName)) { return true; } for (String transitiveDependency : dependentBeans) { if (alreadySeen == null) { alreadySeen = new HashSet<String>(); } alreadySeen.add(beanName); if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } return false; } /** * Determine whether a dependent bean has been registered for the given name. * @param beanName the name of the bean to check */ protected boolean hasDependentBean(String beanName) { return this.dependentBeanMap.containsKey(beanName); } /** * Return the names of all beans which depend on the specified bean, if any. * @param beanName the name of the bean * @return the array of dependent bean names, or an empty array if none */ public String[] getDependentBeans(String beanName) { Set<String> dependentBeans = this.dependentBeanMap.get(beanName); if (dependentBeans == null) { return new String[0]; } return StringUtils.toStringArray(dependentBeans); } /** * Return the names of all beans that the specified bean depends on, if any. * @param beanName the name of the bean * @return the array of names of beans which the bean depends on, * or an empty array if none */ public String[] getDependenciesForBean(String beanName) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName); if (dependenciesForBean == null) { return new String[0]; } return dependenciesForBean.toArray(new String[dependenciesForBean.size()]); } public void destroySingletons() { if (logger.isDebugEnabled()) { logger.debug("Destroying singletons in " + this); } synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); synchronized (this.singletonObjects) { this.singletonObjects.clear(); this.singletonFactories.clear(); this.earlySingletonObjects.clear(); this.registeredSingletons.clear(); this.singletonsCurrentlyInDestruction = false; } } /** * Destroy the given bean. Delegates to {@code destroyBean} * if a corresponding disposable bean instance is found. * @param beanName the name of the bean * @see #destroyBean */ public void destroySingleton(String beanName) { // Remove a registered singleton of the given name, if any. removeSingleton(beanName); // Destroy the corresponding DisposableBean instance. DisposableBean disposableBean; synchronized (this.disposableBeans) { disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } destroyBean(beanName, disposableBean); } /** * Destroy the given bean. Must destroy beans that depend on the given * bean before the bean itself. Should not throw any exceptions. * @param beanName the name of the bean * @param bean the bean instance to destroy */ protected void destroyBean(String beanName, DisposableBean bean) { // Trigger destruction of dependent beans first... Set<String> dependencies = this.dependentBeanMap.remove(beanName); if (dependencies != null) { if (logger.isDebugEnabled()) { logger.debug("Retrieved dependent beans for bean ‘" + beanName + "‘: " + dependencies); } for (String dependentBeanName : dependencies) { destroySingleton(dependentBeanName); } } // Actually destroy the bean now... if (bean != null) { try { bean.destroy(); } catch (Throwable ex) { logger.error("Destroy method on bean with name ‘" + beanName + "‘ threw an exception", ex); } } // Trigger destruction of contained beans... Set<String> containedBeans = this.containedBeanMap.remove(beanName); if (containedBeans != null) { for (String containedBeanName : containedBeans) { destroySingleton(containedBeanName); } } // Remove destroyed bean from other beans‘ dependencies. synchronized (this.dependentBeanMap) { for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { Map.Entry<String, Set<String>> entry = it.next(); Set<String> dependenciesToClean = entry.getValue(); dependenciesToClean.remove(beanName); if (dependenciesToClean.isEmpty()) { it.remove(); } } } // Remove destroyed bean‘s prepared dependency information. this.dependenciesForBeanMap.remove(beanName); } /** * Exposes the singleton mutex to subclasses and external collaborators. * <p>Subclasses should synchronize on the given Object if they perform * any sort of extended singleton creation phase. In particular, subclasses * should <i>not</i> have their own mutexes involved in singleton creation, * to avoid the potential for deadlocks in lazy-init situations. */ public final Object getSingletonMutex() { return this.singletonObjects; } }
二:从bean的实例中获取对象
在getBean方法中,getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope加载bean。总之,我们得到的bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是永恒检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。
无论是从缓存中获取到的bean还是通过不同scope策略加载的bean都只是最原始的bean状态,并不一定是我们最终想要的bean。
(2.1)getObjectForBeanInstance
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { /** * Get the object for the given bean instance, either the bean * instance itself or its created object in case of a FactoryBean. * @param beanInstance the shared bean instance * @param name name that may include factory dereference prefix * @param beanName the canonical bean name * @param mbd the merged bean definition * @return the object to expose for the bean */ protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // Don‘t let calling code try to dereference the factory if the bean isn‘t a factory. if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it‘s a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } }
该方法所做的工作:
- 对FactoryBean正确性的验证。
- 对非FactoryBean不做任何处理。
- 对bean进行转换
- 将从Factory中解析bean的工作委托给getObjectFromFactoryBean
(2.2)getObjectFromFactoryBean
/** * Support base class for singleton registries which need to handle * {@link org.springframework.beans.factory.FactoryBean} instances, * integrated with {@link DefaultSingletonBeanRegistry}‘s singleton management. * * <p>Serves as base class for {@link AbstractBeanFactory}. * * @author Juergen Hoeller * @since 2.5.1 */ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry { /** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */ private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>(16); /** * Determine the type for the given FactoryBean. * @param factoryBean the FactoryBean instance to check * @return the FactoryBean‘s object type, * or {@code null} if the type cannot be determined yet */ protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) { try { if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { @Override public Class<?> run() { return factoryBean.getObjectType(); } }, getAccessControlContext()); } else { return factoryBean.getObjectType(); } } catch (Throwable ex) { // Thrown from the FactoryBean‘s getObjectType implementation. logger.warn("FactoryBean threw exception from getObjectType, despite the contract saying " + "that it should return null if the type of its object cannot be determined yet", ex); return null; } } /** * Obtain an object to expose from the given FactoryBean, if available * in cached form. Quick check for minimal synchronization. * @param beanName the name of the bean * @return the object obtained from the FactoryBean, * or {@code null} if not available */ protected Object getCachedObjectForFactoryBean(String beanName) { Object object = this.factoryBeanObjectCache.get(beanName); return (object != NULL_OBJECT ? object : null); } /** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @param shouldPostProcess whether the bean is subject to post-processing * @return the object obtained from the FactoryBean * @throws BeanCreationException if FactoryBean object creation failed * @see org.springframework.beans.factory.FactoryBean#getObject() */ protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果是单例模式 if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); // Only post-process and store if not put there already during getObject() call above // (e.g. because of circular reference processing triggered by custom getBean calls) Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (object != null && shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean‘s singleton object failed", ex); } } this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); } } return (object != NULL_OBJECT ? object : null); } } else { Object object = doGetObjectFromFactoryBean(factory, beanName); if (object != null && shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean‘s object failed", ex); } } return object; } } /** * Obtain an object to expose from the given FactoryBean. * @param factory the FactoryBean instance * @param beanName the name of the bean * @return the object obtained from the FactoryBean * @throws BeanCreationException if FactoryBean object creation failed * @see org.springframework.beans.factory.FactoryBean#getObject() */ private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = getAccessControlContext(); try { object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { return factory.getObject(); } }, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { object = factory.getObject(); } } catch (FactoryBeanNotInitializedException ex) { throw new BeanCurrentlyInCreationException(beanName, ex.toString()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex); } // Do not accept a null value for a FactoryBean that‘s not fully // initialized yet: Many FactoryBeans just return null then. if (object == null && isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } return object; } /** * Post-process the given object that has been obtained from the FactoryBean. * The resulting object will get exposed for bean references. * <p>The default implementation simply returns the given object as-is. * Subclasses may override this, for example, to apply post-processors. * @param object the object obtained from the FactoryBean. * @param beanName the name of the bean * @return the object to expose * @throws org.springframework.beans.BeansException if any post-processing failed */ protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException { return object; } /** * Get a FactoryBean for the given bean if possible. * @param beanName the name of the bean * @param beanInstance the corresponding bean instance * @return the bean instance as FactoryBean * @throws BeansException if the given bean cannot be exposed as a FactoryBean */ protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException { if (!(beanInstance instanceof FactoryBean)) { throw new BeanCreationException(beanName, "Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean"); } return (FactoryBean<?>) beanInstance; } /** * Overridden to clear the FactoryBean object cache as well. */ @Override protected void removeSingleton(String beanName) { super.removeSingleton(beanName); this.factoryBeanObjectCache.remove(beanName); } /** * Returns the security context for this bean factory. If a security manager * is set, interaction with the user code will be executed using the privileged * of the security context returned by this method. * @see AccessController#getContext() */ protected AccessControlContext getAccessControlContext() { return AccessController.getContext(); } }
三:获取单例
如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了,而Spring中使用getSingleton的重载方法实现bean的加载过程。
(3.1)再次查看DefaultSingletonBeanRegistry 类中方法
/** * Return the (raw) singleton object registered under the given name, * creating and registering a new one if none registered yet. * @param beanName the name of the bean * @param singletonFactory the ObjectFactory to lazily create the singleton * with, if necessary * @return the registered singleton object */ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "‘beanName‘ must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean ‘" + beanName + "‘"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
分析:
(6)将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。
/** * Add the given singleton object to the singleton cache of this factory. * <p>To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
四:准备创建bean
(4.1)AbstractAutowireCapableBeanFactory 中的 createBean 方法
package org.springframework.beans.factory.support; /** * Abstract bean factory superclass that implements default bean creation, * with the full capabilities specified by the {@link RootBeanDefinition} class. * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory} * interface in addition to AbstractBeanFactory‘s {@link #createBean} method. * * <p>Provides bean creation (with constructor resolution), property population, * wiring (including autowiring), and initialization. Handles runtime bean * references, resolves managed collections, calls initialization methods, etc. * Supports autowiring constructors, properties by name, and properties by type. * * <p>The main template method to be implemented by subclasses is * {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}, * used for autowiring by type. In case of a factory which is capable of searching * its bean definitions, matching beans will typically be implemented through such * a search. For other factory styles, simplified matching algorithms can be implemented. * * <p>Note that this class does <i>not</i> assume or implement bean definition * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation * of the {@link org.springframework.beans.factory.ListableBeanFactory} and * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI * view of such a factory, respectively. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop * @author Mark Fisher * @author Costin Leau * @author Chris Beams * @author Sam Brannen * @since 13.02.2004 * @see RootBeanDefinition * @see DefaultListableBeanFactory * @see BeanDefinitionRegistry */ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { /** Strategy for creating bean instances */ private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); /** Resolver strategy for method parameter names */ private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); /** Whether to automatically try to resolve circular references between beans */ private boolean allowCircularReferences = true; /** * Whether to resort to injecting a raw bean instance in case of circular reference, * even if the injected bean eventually got wrapped. */ private boolean allowRawInjectionDespiteWrapping = false; /** * Dependency types to ignore on dependency check and autowire, as Set of * Class objects: for example, String. Default is none. */ private final Set<Class<?>> ignoredDependencyTypes = new HashSet<Class<?>>(); /** * Dependency interfaces to ignore on dependency check and autowire, as Set of * Class objects. By default, only the BeanFactory interface is ignored. */ private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<Class<?>>(); /** Cache of unfinished FactoryBean instances: FactoryBean name --> BeanWrapper */ private final Map<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String, BeanWrapper>(16); /** Cache of filtered PropertyDescriptors: bean Class -> PropertyDescriptor array */ private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache = new ConcurrentHashMap<Class<?>, PropertyDescriptor[]>(256); /** * Create a new AbstractAutowireCapableBeanFactory. */ public AbstractAutowireCapableBeanFactory() { super(); ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); } /** * Create a new AbstractAutowireCapableBeanFactory with the given parent. * @param parentBeanFactory parent bean factory, or {@code null} if none */ public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) { this(); setParentBeanFactory(parentBeanFactory); } /** * Set the instantiation strategy to use for creating bean instances. * Default is CglibSubclassingInstantiationStrategy. * @see CglibSubclassingInstantiationStrategy */ public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) { this.instantiationStrategy = instantiationStrategy; } /** * Return the instantiation strategy to use for creating bean instances. */ protected InstantiationStrategy getInstantiationStrategy() { return this.instantiationStrategy; } /** * Set the ParameterNameDiscoverer to use for resolving method parameter * names if needed (e.g. for constructor names). * <p>Default is a {@link DefaultParameterNameDiscoverer}. */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } /** * Return the ParameterNameDiscoverer to use for resolving method parameter * names if needed. */ protected ParameterNameDiscoverer getParameterNameDiscoverer() { return this.parameterNameDiscoverer; } /** * Set whether to allow circular references between beans - and automatically * try to resolve them. * <p>Note that circular reference resolution means that one of the involved beans * will receive a reference to another bean that is not fully initialized yet. * This can lead to subtle and not-so-subtle side effects on initialization; * it does work fine for many scenarios, though. * <p>Default is "true". Turn this off to throw an exception when encountering * a circular reference, disallowing them completely. * <p><b>NOTE:</b> It is generally recommended to not rely on circular references * between your beans. Refactor your application logic to have the two beans * involved delegate to a third bean that encapsulates their common logic. */ public void setAllowCircularReferences(boolean allowCircularReferences) { this.allowCircularReferences = allowCircularReferences; } /** * Set whether to allow the raw injection of a bean instance into some other * bean‘s property, despite the injected bean eventually getting wrapped * (for example, through AOP auto-proxying). * <p>This will only be used as a last resort in case of a circular reference * that cannot be resolved otherwise: essentially, preferring a raw instance * getting injected over a failure of the entire bean wiring process. * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped * raw beans injected into some of your references, which was Spring 1.2‘s * (arguably unclean) default behavior. * <p><b>NOTE:</b> It is generally recommended to not rely on circular references * between your beans, in particular with auto-proxying involved. * @see #setAllowCircularReferences */ public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) { this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping; } /** * Ignore the given dependency type for autowiring: * for example, String. Default is none. */ public void ignoreDependencyType(Class<?> type) { this.ignoredDependencyTypes.add(type); } /** * Ignore the given dependency interface for autowiring. * <p>This will typically be used by application contexts to register * dependencies that are resolved in other ways, like BeanFactory through * BeanFactoryAware or ApplicationContext through ApplicationContextAware. * <p>By default, only the BeanFactoryAware interface is ignored. * For further types to ignore, invoke this method for each type. * @see org.springframework.beans.factory.BeanFactoryAware * @see org.springframework.context.ApplicationContextAware */ public void ignoreDependencyInterface(Class<?> ifc) { this.ignoredDependencyInterfaces.add(ifc); } @Override public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { super.copyConfigurationFrom(otherFactory); if (otherFactory instanceof AbstractAutowireCapableBeanFactory) { AbstractAutowireCapableBeanFactory otherAutowireFactory = (AbstractAutowireCapableBeanFactory) otherFactory; this.instantiationStrategy = otherAutowireFactory.instantiationStrategy; this.allowCircularReferences = otherAutowireFactory.allowCircularReferences; this.ignoredDependencyTypes.addAll(otherAutowireFactory.ignoredDependencyTypes); this.ignoredDependencyInterfaces.addAll(otherAutowireFactory.ignoredDependencyInterfaces); } } //------------------------------------------------------------------------- // Typical methods for creating and populating external bean instances //------------------------------------------------------------------------- @Override @SuppressWarnings("unchecked") public <T> T createBean(Class<T> beanClass) throws BeansException { // Use prototype bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass); bd.setScope(SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader()); return (T) createBean(beanClass.getName(), bd, null); } @Override public void autowireBean(Object existingBean) { // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean)); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader()); BeanWrapper bw = new BeanWrapperImpl(existingBean); initBeanWrapper(bw); populateBean(bd.getBeanClass().getName(), bd, bw); } @Override public Object configureBean(Object existingBean, String beanName) throws BeansException { markBeanAsCreated(beanName); BeanDefinition mbd = getMergedBeanDefinition(beanName); RootBeanDefinition bd = null; if (mbd instanceof RootBeanDefinition) { RootBeanDefinition rbd = (RootBeanDefinition) mbd; bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition()); } if (!mbd.isPrototype()) { if (bd == null) { bd = new RootBeanDefinition(mbd); } bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader()); } BeanWrapper bw = new BeanWrapperImpl(existingBean); initBeanWrapper(bw); populateBean(beanName, bd, bw); return initializeBean(beanName, existingBean, bd); } @Override public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException { return resolveDependency(descriptor, requestingBeanName, null, null); } //------------------------------------------------------------------------- // Specialized methods for fine-grained control over the bean lifecycle //------------------------------------------------------------------------- @Override public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException { // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); return createBean(beanClass.getName(), bd, null); } @Override public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException { // Use non-singleton bean definition, to avoid registering bean as dependent bean. final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) { return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance(); } else { Object bean; final BeanFactory parent = this; if (System.getSecurityManager() != null) { bean = AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { return getInstantiationStrategy().instantiate(bd, null, parent); } }, getAccessControlContext()); } else { bean = getInstantiationStrategy().instantiate(bd, null, parent); } populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean)); return bean; } } @Override public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException { if (autowireMode == AUTOWIRE_CONSTRUCTOR) { throw new IllegalArgumentException("AUTOWIRE_CONSTRUCTOR not supported for existing bean instance"); } // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean), autowireMode, dependencyCheck); bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); BeanWrapper bw = new BeanWrapperImpl(existingBean); initBeanWrapper(bw); populateBean(bd.getBeanClass().getName(), bd, bw); } @Override public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException { markBeanAsCreated(beanName); BeanDefinition bd = getMergedBeanDefinition(beanName); BeanWrapper bw = new BeanWrapperImpl(existingBean); initBeanWrapper(bw); applyPropertyValues(beanName, bd, bw, bd.getPropertyValues()); } @Override public Object initializeBean(Object existingBean, String beanName) { return initializeBean(beanName, existingBean, null); } @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; } @Override public void destroyBean(Object existingBean) { new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy(); } //--------------------------------------------------------------------- // Implementation of relevant AbstractBeanFactory template methods //--------------------------------------------------------------------- /** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean ‘" + beanName + "‘"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean ‘" + beanName + "‘"); } return beanInstance; } /** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); mbd.resolvedTargetType = beanType; // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean ‘" + beanName + "‘ to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) {
//调用初始化方法,比如init-method exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name ‘" + beanName + "‘ has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example."); } } } } // Register bean as disposable. try {
//根据scope注册bean registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; } @Override protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch); // Apply SmartInstantiationAwareBeanPostProcessors to predict the // eventual type after a before-instantiation shortcut. if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Class<?> predicted = ibp.predictBeanType(targetType, beanName); if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] || FactoryBean.class.isAssignableFrom(predicted))) { return predicted; } } } } return targetType; } /** * Determine the target type for the given bean definition. * @param beanName the name of the bean (for error handling purposes) * @param mbd the merged bean definition for the bean * @param typesToMatch the types to match in case of internal type matching purposes * (also signals that the returned {@code Class} will never be exposed to application code) * @return the type for the bean if determinable, or {@code null} otherwise */ protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { Class<?> targetType = mbd.getTargetType(); if (targetType == null) { targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) : resolveBeanClass(mbd, beanName, typesToMatch)); if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) { mbd.resolvedTargetType = targetType; } } return targetType; } /** * Determine the target type for the given bean definition which is based on * a factory method. Only called if there is no singleton instance registered * for the target bean already. * <p>This implementation determines the type matching {@link #createBean}‘s * different creation strategies. As far as possible, we‘ll perform static * type checking to avoid creation of the target bean. * @param beanName the name of the bean (for error handling purposes) * @param mbd the merged bean definition for the bean * @param typesToMatch the types to match in case of internal type matching purposes * (also signals that the returned {@code Class} will never be exposed to application code) * @return the type for the bean if determinable, or {@code null} otherwise * @see #createBean */ protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { ResolvableType cachedReturnType = mbd.factoryMethodReturnType; if (cachedReturnType != null) { return cachedReturnType.resolve(); } Class<?> factoryClass; boolean isStatic = true; String factoryBeanName = mbd.getFactoryBeanName(); if (factoryBeanName != null) { if (factoryBeanName.equals(beanName)) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition"); } // Check declared factory method return type on factory class. factoryClass = getType(factoryBeanName); isStatic = false; } else { // Check declared factory method return type on bean class. factoryClass = resolveBeanClass(mbd, beanName, typesToMatch); } if (factoryClass == null) { return null; } factoryClass = ClassUtils.getUserClass(factoryClass); // If all factory methods have the same return type, return that type. // Can‘t clearly figure out exact method due to type converting / autowiring! Class<?> commonType = null; Method uniqueCandidate = null; int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount(); Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass); for (Method factoryMethod : candidates) { if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic && factoryMethod.getName().equals(mbd.getFactoryMethodName()) && factoryMethod.getParameterTypes().length >= minNrOfArgs) { // Declared type variables to inspect? if (factoryMethod.getTypeParameters().length > 0) { try { // Fully resolve parameter names and argument values. Class<?>[] paramTypes = factoryMethod.getParameterTypes(); String[] paramNames = null; ParameterNameDiscoverer pnd = getParameterNameDiscoverer(); if (pnd != null) { paramNames = pnd.getParameterNames(factoryMethod); } ConstructorArgumentValues cav = mbd.getConstructorArgumentValues(); Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length); Object[] args = new Object[paramTypes.length]; for (int i = 0; i < args.length; i++) { ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue( i, paramTypes[i], (paramNames != null ? paramNames[i] : null), usedValueHolders); if (valueHolder == null) { valueHolder = cav.getGenericArgumentValue(null, null, usedValueHolders); } if (valueHolder != null) { args[i] = valueHolder.getValue(); usedValueHolders.add(valueHolder); } } Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod( factoryMethod, args, getBeanClassLoader()); if (returnType != null) { uniqueCandidate = (commonType == null ? factoryMethod : null); commonType = ClassUtils.determineCommonAncestor(returnType, commonType); if (commonType == null) { // Ambiguous return types found: return null to indicate "not determinable". return null; } } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to resolve generic return type for factory method: " + ex); } } } else { uniqueCandidate = (commonType == null ? factoryMethod : null); commonType = ClassUtils.determineCommonAncestor(factoryMethod.getReturnType(), commonType); if (commonType == null) { // Ambiguous return types found: return null to indicate "not determinable". return null; } } } } if (commonType != null) { // Clear return type found: all factory methods return same type. mbd.factoryMethodReturnType = (uniqueCandidate != null ? ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType)); } return commonType; } /** * This implementation attempts to query the FactoryBean‘s generic parameter metadata * if present to determine the object type. If not present, i.e. the FactoryBean is * declared as a raw type, checks the FactoryBean‘s {@code getObjectType} method * on a plain instance of the FactoryBean, without bean properties applied yet. * If this doesn‘t return a type yet, a full creation of the FactoryBean is * used as fallback (through delegation to the superclass‘s implementation). * <p>The shortcut check for a FactoryBean is only applied in case of a singleton * FactoryBean. If the FactoryBean instance itself is not kept as singleton, * it will be fully created to check the type of its exposed object. */ @Override protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) { String factoryBeanName = mbd.getFactoryBeanName(); String factoryMethodName = mbd.getFactoryMethodName(); if (factoryBeanName != null) { if (factoryMethodName != null) { // Try to obtain the FactoryBean‘s object type from its factory method declaration // without instantiating the containing bean at all. BeanDefinition fbDef = getBeanDefinition(factoryBeanName); if (fbDef instanceof AbstractBeanDefinition) { AbstractBeanDefinition afbDef = (AbstractBeanDefinition) fbDef; if (afbDef.hasBeanClass()) { Class<?> result = getTypeForFactoryBeanFromMethod(afbDef.getBeanClass(), factoryMethodName); if (result != null) { return result; } } } } // If not resolvable above and the referenced factory bean doesn‘t exist yet, // exit here - we don‘t want to force the creation of another bean just to // obtain a FactoryBean‘s object type... if (!isBeanEligibleForMetadataCaching(factoryBeanName)) { return null; } } // Let‘s obtain a shortcut instance for an early getObjectType() call... FactoryBean<?> fb = (mbd.isSingleton() ? getSingletonFactoryBeanForTypeCheck(beanName, mbd) : getNonSingletonFactoryBeanForTypeCheck(beanName, mbd)); if (fb != null) { // Try to obtain the FactoryBean‘s object type from this early stage of the instance. Class<?> result = getTypeForFactoryBean(fb); if (result != null) { return result; } else { // No type found for shortcut FactoryBean instance: // fall back to full creation of the FactoryBean instance. return super.getTypeForFactoryBean(beanName, mbd); } } if (factoryBeanName == null && mbd.hasBeanClass()) { // No early bean instantiation possible: determine FactoryBean‘s type from // static factory method signature or from class inheritance hierarchy... if (factoryMethodName != null) { return getTypeForFactoryBeanFromMethod(mbd.getBeanClass(), factoryMethodName); } else { return GenericTypeResolver.resolveTypeArgument(mbd.getBeanClass(), FactoryBean.class); } } return null; } /** * Introspect the factory method signatures on the given bean class, * trying to find a common {@code FactoryBean} object type declared there. * @param beanClass the bean class to find the factory method on * @param factoryMethodName the name of the factory method * @return the common {@code FactoryBean} object type, or {@code null} if none */ private Class<?> getTypeForFactoryBeanFromMethod(Class<?> beanClass, final String factoryMethodName) { class Holder { Class<?> value = null; } final Holder objectType = new Holder(); // CGLIB subclass methods hide generic parameters; look at the original user class. Class<?> fbClass = ClassUtils.getUserClass(beanClass); // Find the given factory method, taking into account that in the case of // @Bean methods, there may be parameters present. ReflectionUtils.doWithMethods(fbClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) { if (method.getName().equals(factoryMethodName) && FactoryBean.class.isAssignableFrom(method.getReturnType())) { Class<?> currentType = GenericTypeResolver.resolveReturnTypeArgument( method, FactoryBean.class); if (currentType != null) { objectType.value = ClassUtils.determineCommonAncestor(currentType, objectType.value); } } } }); return (objectType.value != null && Object.class != objectType.value ? objectType.value : null); } /** * Obtain a reference for early access to the specified bean, * typically for the purpose of resolving a circular reference. * @param beanName the name of the bean (for error handling purposes) * @param mbd the merged bean definition for the bean * @param bean the raw bean instance * @return the object to expose as bean reference */ protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); if (exposedObject == null) { return null; } } } } return exposedObject; } //--------------------------------------------------------------------- // Implementation methods //--------------------------------------------------------------------- /** * Obtain a "shortcut" singleton FactoryBean instance to use for a * {@code getObjectType()} call, without full initialization of the FactoryBean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the FactoryBean instance, or {@code null} to indicate * that we couldn‘t obtain a shortcut FactoryBean instance */ private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) { synchronized (getSingletonMutex()) { BeanWrapper bw = this.factoryBeanInstanceCache.get(beanName); if (bw != null) { return (FactoryBean<?>) bw.getWrappedInstance(); } if (isSingletonCurrentlyInCreation(beanName) || (mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) { return null; } Object instance = null; try { // Mark this bean as currently in creation, even if just partially. beforeSingletonCreation(beanName); // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. instance = resolveBeforeInstantiation(beanName, mbd); if (instance == null) { bw = createBeanInstance(beanName, mbd, null); instance = bw.getWrappedInstance(); } } finally { // Finished partial creation of this bean. afterSingletonCreation(beanName); } FactoryBean<?> fb = getFactoryBean(beanName, instance); if (bw != null) { this.factoryBeanInstanceCache.put(beanName, bw); } return fb; } } /** * Obtain a "shortcut" non-singleton FactoryBean instance to use for a * {@code getObjectType()} call, without full initialization of the FactoryBean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the FactoryBean instance, or {@code null} to indicate * that we couldn‘t obtain a shortcut FactoryBean instance */ private FactoryBean<?> getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) { if (isPrototypeCurrentlyInCreation(beanName)) { return null; } Object instance = null; try { // Mark this bean as currently in creation, even if just partially. beforePrototypeCreation(beanName); // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. instance = resolveBeforeInstantiation(beanName, mbd); if (instance == null) { BeanWrapper bw = createBeanInstance(beanName, mbd, null); instance = bw.getWrappedInstance(); } } catch (BeanCreationException ex) { // Can only happen when getting a FactoryBean. if (logger.isDebugEnabled()) { logger.debug("Bean creation exception on non-singleton FactoryBean type check: " + ex); } onSuppressedException(ex); return null; } finally { // Finished partial creation of this bean. afterPrototypeCreation(beanName); } return getFactoryBean(beanName, instance); } /** * Apply MergedBeanDefinitionPostProcessors to the specified bean definition, * invoking their {@code postProcessMergedBeanDefinition} methods. * @param mbd the merged bean definition for the bean * @param beanType the actual type of the managed bean instance * @param beanName the name of the bean * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition */ protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } } /** * Apply before-instantiation post-processors, resolving whether there is a * before-instantiation shortcut for the specified bean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the shortcut-determined bean instance, or {@code null} if none */ protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; } /** * Apply InstantiationAwareBeanPostProcessors to the specified bean definition * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods. * <p>Any returned object will be used as the bean instead of actually instantiating * the target bean. A {@code null} return value from the post-processor will * result in the target bean being instantiated. * @param beanClass the class of the bean to be instantiated * @param beanName the name of the bean * @return the bean object to use instead of a default instance of the target bean, or {@code null} * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation */ protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; } /** * Create a new instance for the specified bean, using an appropriate instantiation strategy: * factory method, constructor autowiring, or simple instantiation. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return BeanWrapper for the new instance * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName()); } if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // Need to determine the constructor... Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); } /** * Determine candidate constructors to use for the given bean, checking all registered * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}. * @param beanClass the raw class of the bean * @param beanName the name of the bean * @return the candidate constructors, or {@code null} if none specified * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors */ protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName) throws BeansException { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; } /** * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return BeanWrapper for the new instance */ protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { return getInstantiationStrategy().instantiate(mbd, beanName, parent); } }, getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } } /** * Instantiate the bean using a named factory method. The method may be static, if the * mbd parameter specifies a class, rather than a factoryBean, or an instance variable * on a factory object itself configured using Dependency Injection. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) * @return BeanWrapper for the new instance * @see #getBean(String, Object[]) */ protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); } /** * "autowire constructor" (with constructor arguments by type) behavior. * Also applied if explicit constructor argument values are specified, * matching all remaining arguments with beans from the bean factory. * <p>This corresponds to constructor injection: In this mode, a Spring * bean factory is able to host components that expect constructor-based * dependency resolution. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param ctors the chosen candidate constructors * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) * @return BeanWrapper for the new instance */ protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) { return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); } /** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */ protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); } /** * Fill in any missing property values with references to * other beans in this factory if autowire is set to "byName". * @param beanName the name of the bean we‘re wiring up. * Useful for debugging messages; not used functionally. * @param mbd bean definition to update through autowiring * @param bw BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { Object bean = getBean(propertyName); pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); if (logger.isDebugEnabled()) { logger.debug("Added autowiring by name from bean name ‘" + beanName + "‘ via property ‘" + propertyName + "‘ to bean named ‘" + propertyName + "‘"); } } else { if (logger.isTraceEnabled()) { logger.trace("Not autowiring property ‘" + propertyName + "‘ of bean ‘" + beanName + "‘ by name: no matching bean found"); } } } } /** * Abstract method defining "autowire by type" (bean properties by type) behavior. * <p>This is like PicoContainer default, in which there must be exactly one bean * of the property type in the bean factory. This makes bean factories simple to * configure for small namespaces, but doesn‘t work as well as standard Spring * behavior for bigger applications. * @param beanName the name of the bean to autowire by type * @param mbd the merged bean definition to update through autowiring * @param bw BeanWrapper from which we can obtain information about the bean * @param pvs the PropertyValues to register wired objects with */ protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); // Don‘t try autowiring by type for type Object: never makes sense, // even if it technically is a unsatisfied, non-simple property. if (Object.class != pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); if (logger.isDebugEnabled()) { logger.debug("Autowiring by type from bean name ‘" + beanName + "‘ via property ‘" + propertyName + "‘ to bean named ‘" + autowiredBeanName + "‘"); } } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } } /** * Return an array of non-simple bean properties that are unsatisfied. * These are probably unsatisfied references to other beans in the * factory. Does not include simple properties like primitives or Strings. * @param mbd the merged bean definition the bean was created with * @param bw the BeanWrapper the bean was created with * @return an array of bean property names * @see org.springframework.beans.BeanUtils#isSimpleProperty */ protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { Set<String> result = new TreeSet<String>(); PropertyValues pvs = mbd.getPropertyValues(); PropertyDescriptor[] pds = bw.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) { result.add(pd.getName()); } } return StringUtils.toStringArray(result); } /** * Extract a filtered set of PropertyDescriptors from the given BeanWrapper, * excluding ignored dependency types or properties defined on ignored dependency interfaces. * @param bw the BeanWrapper the bean was created with * @param cache whether to cache filtered PropertyDescriptors for the given bean Class * @return the filtered PropertyDescriptors * @see #isExcludedFromDependencyCheck * @see #filterPropertyDescriptorsForDependencyCheck(org.springframework.beans.BeanWrapper) */ protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) { PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass()); if (filtered == null) { filtered = filterPropertyDescriptorsForDependencyCheck(bw); if (cache) { PropertyDescriptor[] existing = this.filteredPropertyDescriptorsCache.putIfAbsent(bw.getWrappedClass(), filtered); if (existing != null) { filtered = existing; } } } return filtered; } /** * Extract a filtered set of PropertyDescriptors from the given BeanWrapper, * excluding ignored dependency types or properties defined on ignored dependency interfaces. * @param bw the BeanWrapper the bean was created with * @return the filtered PropertyDescriptors * @see #isExcludedFromDependencyCheck */ protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) { List<PropertyDescriptor> pds = new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors())); for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) { PropertyDescriptor pd = it.next(); if (isExcludedFromDependencyCheck(pd)) { it.remove(); } } return pds.toArray(new PropertyDescriptor[pds.size()]); } /** * Determine whether the given bean property is excluded from dependency checks. * <p>This implementation excludes properties defined by CGLIB and * properties whose type matches an ignored dependency type or which * are defined by an ignored dependency interface. * @param pd the PropertyDescriptor of the bean property * @return whether the bean property is excluded * @see #ignoreDependencyType(Class) * @see #ignoreDependencyInterface(Class) */ protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) { return (AutowireUtils.isExcludedFromDependencyCheck(pd) || this.ignoredDependencyTypes.contains(pd.getPropertyType()) || AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces)); } /** * Perform a dependency check that all properties exposed have been set, * if desired. Dependency checks can be objects (collaborating beans), * simple (primitives and String), or all (both). * @param beanName the name of the bean * @param mbd the merged bean definition the bean was created with * @param pds the relevant property descriptors for the target bean * @param pvs the property values to be applied to the bean * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor) */ protected void checkDependencies( String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs) throws UnsatisfiedDependencyException { int dependencyCheck = mbd.getDependencyCheck(); for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) { boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType()); boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) || (isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) || (!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS); if (unsatisfied) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(), "Set this property value or disable dependency checking for this bean."); } } } } /** * Apply the given property values, resolving any runtime references * to other beans in this bean factory. Must use deep copy, so we * don‘t permanently modify this property. * @param beanName the bean name passed for better exception information * @param mbd the merged bean definition * @param bw the BeanWrapper wrapping the target object * @param pvs the new property values */ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs == null || pvs.isEmpty()) { return; } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (System.getSecurityManager() != null) { if (bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } } if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } /** * Convert the given value for the specified target property. */ private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) { if (converter instanceof BeanWrapperImpl) { return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName); } else { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam); } } /** * Initialize the given bean instance, applying factory callbacks * as well as init methods and bean post processors. * <p>Called from {@link #createBean} for traditionally defined beans, * and from {@link #initializeBean} for existing bean instances. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the bean definition that the bean was created with * (can also be {@code null}, if given an existing bean instance) * @return the initialized bean instance (potentially wrapped) * @see BeanNameAware * @see BeanClassLoaderAware * @see BeanFactoryAware * @see #applyBeanPostProcessorsBeforeInitialization * @see #invokeInitMethods * @see #applyBeanPostProcessorsAfterInitialization */ protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } } /** * Give a bean a chance to react now all its properties are set, * and a chance to know about its owning bean factory (this object). * This means checking whether the bean implements InitializingBean or defines * a custom init method, and invoking the necessary callback(s) if it does. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the merged bean definition that the bean was created with * (can also be {@code null}, if given an existing bean instance) * @throws Throwable if thrown by init methods or by the invocation process * @see #invokeCustomInitMethod */ protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name ‘" + beanName + "‘"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } } /** * Invoke the specified custom init method on the given bean. * Called by invokeInitMethods. * <p>Can be overridden in subclasses for custom resolution of init * methods with arguments. * @see #invokeInitMethods */ protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { String initMethodName = mbd.getInitMethodName(); final Method initMethod = (mbd.isNonPublicAccessAllowed() ? BeanUtils.findMethod(bean.getClass(), initMethodName) : ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); if (initMethod == null) { if (mbd.isEnforceInitMethod()) { throw new BeanDefinitionValidationException("Couldn‘t find an init method named ‘" + initMethodName + "‘ on bean with name ‘" + beanName + "‘"); } else { if (logger.isDebugEnabled()) { logger.debug("No default init method named ‘" + initMethodName + "‘ found on bean with name ‘" + beanName + "‘"); } // Ignore non-existent default lifecycle methods. return; } } if (logger.isDebugEnabled()) { logger.debug("Invoking init method ‘" + initMethodName + "‘ on bean with name ‘" + beanName + "‘"); } if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ReflectionUtils.makeAccessible(initMethod); return null; } }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { initMethod.invoke(bean); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { InvocationTargetException ex = (InvocationTargetException) pae.getException(); throw ex.getTargetException(); } } else { try { ReflectionUtils.makeAccessible(initMethod); initMethod.invoke(bean); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } /** * Applies the {@code postProcessAfterInitialization} callback of all * registered BeanPostProcessors, giving them a chance to post-process the * object obtained from FactoryBeans (for example, to auto-proxy them). * @see #applyBeanPostProcessorsAfterInitialization */ @Override protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { return applyBeanPostProcessorsAfterInitialization(object, beanName); } /** * Overridden to clear FactoryBean instance cache as well. */ @Override protected void removeSingleton(String beanName) { super.removeSingleton(beanName); this.factoryBeanInstanceCache.remove(beanName); } /** * Special DependencyDescriptor variant for Spring‘s good old autowire="byType" mode. * Always optional; never considering the parameter name for choosing a primary candidate. */ @SuppressWarnings("serial") private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor { public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) { super(methodParameter, false, eager); } @Override public String getDependencyName() { return null; } } }