001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory.support;
018
019import java.beans.PropertyEditor;
020import java.security.AccessControlContext;
021import java.security.AccessController;
022import java.security.PrivilegedAction;
023import java.security.PrivilegedActionException;
024import java.security.PrivilegedExceptionAction;
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.HashMap;
029import java.util.HashSet;
030import java.util.LinkedHashMap;
031import java.util.LinkedHashSet;
032import java.util.List;
033import java.util.Map;
034import java.util.Set;
035import java.util.concurrent.ConcurrentHashMap;
036import java.util.concurrent.CopyOnWriteArrayList;
037
038import org.springframework.beans.BeanUtils;
039import org.springframework.beans.BeanWrapper;
040import org.springframework.beans.BeansException;
041import org.springframework.beans.PropertyEditorRegistrar;
042import org.springframework.beans.PropertyEditorRegistry;
043import org.springframework.beans.PropertyEditorRegistrySupport;
044import org.springframework.beans.SimpleTypeConverter;
045import org.springframework.beans.TypeConverter;
046import org.springframework.beans.TypeMismatchException;
047import org.springframework.beans.factory.BeanCreationException;
048import org.springframework.beans.factory.BeanCurrentlyInCreationException;
049import org.springframework.beans.factory.BeanDefinitionStoreException;
050import org.springframework.beans.factory.BeanFactory;
051import org.springframework.beans.factory.BeanFactoryUtils;
052import org.springframework.beans.factory.BeanIsAbstractException;
053import org.springframework.beans.factory.BeanIsNotAFactoryException;
054import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
055import org.springframework.beans.factory.CannotLoadBeanClassException;
056import org.springframework.beans.factory.FactoryBean;
057import org.springframework.beans.factory.NoSuchBeanDefinitionException;
058import org.springframework.beans.factory.SmartFactoryBean;
059import org.springframework.beans.factory.config.BeanDefinition;
060import org.springframework.beans.factory.config.BeanDefinitionHolder;
061import org.springframework.beans.factory.config.BeanExpressionContext;
062import org.springframework.beans.factory.config.BeanExpressionResolver;
063import org.springframework.beans.factory.config.BeanPostProcessor;
064import org.springframework.beans.factory.config.ConfigurableBeanFactory;
065import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
066import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
067import org.springframework.beans.factory.config.Scope;
068import org.springframework.core.AttributeAccessor;
069import org.springframework.core.DecoratingClassLoader;
070import org.springframework.core.NamedThreadLocal;
071import org.springframework.core.ResolvableType;
072import org.springframework.core.convert.ConversionService;
073import org.springframework.core.log.LogMessage;
074import org.springframework.lang.Nullable;
075import org.springframework.util.Assert;
076import org.springframework.util.ClassUtils;
077import org.springframework.util.ObjectUtils;
078import org.springframework.util.StringUtils;
079import org.springframework.util.StringValueResolver;
080
081/**
082 * Abstract base class for {@link org.springframework.beans.factory.BeanFactory}
083 * implementations, providing the full capabilities of the
084 * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI.
085 * Does <i>not</i> assume a listable bean factory: can therefore also be used
086 * as base class for bean factory implementations which obtain bean definitions
087 * from some backend resource (where bean definition access is an expensive operation).
088 *
089 * <p>This class provides a singleton cache (through its base class
090 * {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry},
091 * singleton/prototype determination, {@link org.springframework.beans.factory.FactoryBean}
092 * handling, aliases, bean definition merging for child bean definitions,
093 * and bean destruction ({@link org.springframework.beans.factory.DisposableBean}
094 * interface, custom destroy methods). Furthermore, it can manage a bean factory
095 * hierarchy (delegating to the parent in case of an unknown bean), through implementing
096 * the {@link org.springframework.beans.factory.HierarchicalBeanFactory} interface.
097 *
098 * <p>The main template methods to be implemented by subclasses are
099 * {@link #getBeanDefinition} and {@link #createBean}, retrieving a bean definition
100 * for a given bean name and creating a bean instance for a given bean definition,
101 * respectively. Default implementations of those operations can be found in
102 * {@link DefaultListableBeanFactory} and {@link AbstractAutowireCapableBeanFactory}.
103 *
104 * @author Rod Johnson
105 * @author Juergen Hoeller
106 * @author Costin Leau
107 * @author Chris Beams
108 * @author Phillip Webb
109 * @since 15 April 2001
110 * @see #getBeanDefinition
111 * @see #createBean
112 * @see AbstractAutowireCapableBeanFactory#createBean
113 * @see DefaultListableBeanFactory#getBeanDefinition
114 */
115public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
116
117        /** Parent bean factory, for bean inheritance support. */
118        @Nullable
119        private BeanFactory parentBeanFactory;
120
121        /** ClassLoader to resolve bean class names with, if necessary. */
122        @Nullable
123        private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
124
125        /** ClassLoader to temporarily resolve bean class names with, if necessary. */
126        @Nullable
127        private ClassLoader tempClassLoader;
128
129        /** Whether to cache bean metadata or rather reobtain it for every access. */
130        private boolean cacheBeanMetadata = true;
131
132        /** Resolution strategy for expressions in bean definition values. */
133        @Nullable
134        private BeanExpressionResolver beanExpressionResolver;
135
136        /** Spring ConversionService to use instead of PropertyEditors. */
137        @Nullable
138        private ConversionService conversionService;
139
140        /** Custom PropertyEditorRegistrars to apply to the beans of this factory. */
141        private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);
142
143        /** Custom PropertyEditors to apply to the beans of this factory. */
144        private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);
145
146        /** A custom TypeConverter to use, overriding the default PropertyEditor mechanism. */
147        @Nullable
148        private TypeConverter typeConverter;
149
150        /** String resolvers to apply e.g. to annotation attribute values. */
151        private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();
152
153        /** BeanPostProcessors to apply. */
154        private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
155
156        /** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */
157        private volatile boolean hasInstantiationAwareBeanPostProcessors;
158
159        /** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */
160        private volatile boolean hasDestructionAwareBeanPostProcessors;
161
162        /** Map from scope identifier String to corresponding Scope. */
163        private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
164
165        /** Security context used when running with a SecurityManager. */
166        @Nullable
167        private SecurityContextProvider securityContextProvider;
168
169        /** Map from bean name to merged RootBeanDefinition. */
170        private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
171
172        /** Names of beans that have already been created at least once. */
173        private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
174
175        /** Names of beans that are currently in creation. */
176        private final ThreadLocal<Object> prototypesCurrentlyInCreation =
177                        new NamedThreadLocal<>("Prototype beans currently in creation");
178
179
180        /**
181         * Create a new AbstractBeanFactory.
182         */
183        public AbstractBeanFactory() {
184        }
185
186        /**
187         * Create a new AbstractBeanFactory with the given parent.
188         * @param parentBeanFactory parent bean factory, or {@code null} if none
189         * @see #getBean
190         */
191        public AbstractBeanFactory(@Nullable BeanFactory parentBeanFactory) {
192                this.parentBeanFactory = parentBeanFactory;
193        }
194
195
196        //---------------------------------------------------------------------
197        // Implementation of BeanFactory interface
198        //---------------------------------------------------------------------
199
200        @Override
201        public Object getBean(String name) throws BeansException {
202                return doGetBean(name, null, null, false);
203        }
204
205        @Override
206        public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
207                return doGetBean(name, requiredType, null, false);
208        }
209
210        @Override
211        public Object getBean(String name, Object... args) throws BeansException {
212                return doGetBean(name, null, args, false);
213        }
214
215        /**
216         * Return an instance, which may be shared or independent, of the specified bean.
217         * @param name the name of the bean to retrieve
218         * @param requiredType the required type of the bean to retrieve
219         * @param args arguments to use when creating a bean instance using explicit arguments
220         * (only applied when creating a new instance as opposed to retrieving an existing one)
221         * @return an instance of the bean
222         * @throws BeansException if the bean could not be created
223         */
224        public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
225                        throws BeansException {
226
227                return doGetBean(name, requiredType, args, false);
228        }
229
230        /**
231         * Return an instance, which may be shared or independent, of the specified bean.
232         * @param name the name of the bean to retrieve
233         * @param requiredType the required type of the bean to retrieve
234         * @param args arguments to use when creating a bean instance using explicit arguments
235         * (only applied when creating a new instance as opposed to retrieving an existing one)
236         * @param typeCheckOnly whether the instance is obtained for a type check,
237         * not for actual use
238         * @return an instance of the bean
239         * @throws BeansException if the bean could not be created
240         */
241        @SuppressWarnings("unchecked")
242        protected <T> T doGetBean(
243                        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
244                        throws BeansException {
245
246                String beanName = transformedBeanName(name);
247                Object bean;
248
249                // Eagerly check singleton cache for manually registered singletons.
250                Object sharedInstance = getSingleton(beanName);
251                if (sharedInstance != null && args == null) {
252                        if (logger.isTraceEnabled()) {
253                                if (isSingletonCurrentlyInCreation(beanName)) {
254                                        logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
255                                                        "' that is not fully initialized yet - a consequence of a circular reference");
256                                }
257                                else {
258                                        logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
259                                }
260                        }
261                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
262                }
263
264                else {
265                        // Fail if we're already creating this bean instance:
266                        // We're assumably within a circular reference.
267                        if (isPrototypeCurrentlyInCreation(beanName)) {
268                                throw new BeanCurrentlyInCreationException(beanName);
269                        }
270
271                        // Check if bean definition exists in this factory.
272                        BeanFactory parentBeanFactory = getParentBeanFactory();
273                        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
274                                // Not found -> check parent.
275                                String nameToLookup = originalBeanName(name);
276                                if (parentBeanFactory instanceof AbstractBeanFactory) {
277                                        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
278                                                        nameToLookup, requiredType, args, typeCheckOnly);
279                                }
280                                else if (args != null) {
281                                        // Delegation to parent with explicit args.
282                                        return (T) parentBeanFactory.getBean(nameToLookup, args);
283                                }
284                                else if (requiredType != null) {
285                                        // No args -> delegate to standard getBean method.
286                                        return parentBeanFactory.getBean(nameToLookup, requiredType);
287                                }
288                                else {
289                                        return (T) parentBeanFactory.getBean(nameToLookup);
290                                }
291                        }
292
293                        if (!typeCheckOnly) {
294                                markBeanAsCreated(beanName);
295                        }
296
297                        try {
298                                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
299                                checkMergedBeanDefinition(mbd, beanName, args);
300
301                                // Guarantee initialization of beans that the current bean depends on.
302                                String[] dependsOn = mbd.getDependsOn();
303                                if (dependsOn != null) {
304                                        for (String dep : dependsOn) {
305                                                if (isDependent(beanName, dep)) {
306                                                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
307                                                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
308                                                }
309                                                registerDependentBean(dep, beanName);
310                                                try {
311                                                        getBean(dep);
312                                                }
313                                                catch (NoSuchBeanDefinitionException ex) {
314                                                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
315                                                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
316                                                }
317                                        }
318                                }
319
320                                // Create bean instance.
321                                if (mbd.isSingleton()) {
322                                        sharedInstance = getSingleton(beanName, () -> {
323                                                try {
324                                                        return createBean(beanName, mbd, args);
325                                                }
326                                                catch (BeansException ex) {
327                                                        // Explicitly remove instance from singleton cache: It might have been put there
328                                                        // eagerly by the creation process, to allow for circular reference resolution.
329                                                        // Also remove any beans that received a temporary reference to the bean.
330                                                        destroySingleton(beanName);
331                                                        throw ex;
332                                                }
333                                        });
334                                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
335                                }
336
337                                else if (mbd.isPrototype()) {
338                                        // It's a prototype -> create a new instance.
339                                        Object prototypeInstance = null;
340                                        try {
341                                                beforePrototypeCreation(beanName);
342                                                prototypeInstance = createBean(beanName, mbd, args);
343                                        }
344                                        finally {
345                                                afterPrototypeCreation(beanName);
346                                        }
347                                        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
348                                }
349
350                                else {
351                                        String scopeName = mbd.getScope();
352                                        if (!StringUtils.hasLength(scopeName)) {
353                                                throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'");
354                                        }
355                                        Scope scope = this.scopes.get(scopeName);
356                                        if (scope == null) {
357                                                throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
358                                        }
359                                        try {
360                                                Object scopedInstance = scope.get(beanName, () -> {
361                                                        beforePrototypeCreation(beanName);
362                                                        try {
363                                                                return createBean(beanName, mbd, args);
364                                                        }
365                                                        finally {
366                                                                afterPrototypeCreation(beanName);
367                                                        }
368                                                });
369                                                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
370                                        }
371                                        catch (IllegalStateException ex) {
372                                                throw new BeanCreationException(beanName,
373                                                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
374                                                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
375                                                                ex);
376                                        }
377                                }
378                        }
379                        catch (BeansException ex) {
380                                cleanupAfterBeanCreationFailure(beanName);
381                                throw ex;
382                        }
383                }
384
385                // Check if required type matches the type of the actual bean instance.
386                if (requiredType != null && !requiredType.isInstance(bean)) {
387                        try {
388                                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
389                                if (convertedBean == null) {
390                                        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
391                                }
392                                return convertedBean;
393                        }
394                        catch (TypeMismatchException ex) {
395                                if (logger.isTraceEnabled()) {
396                                        logger.trace("Failed to convert bean '" + name + "' to required type '" +
397                                                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
398                                }
399                                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
400                        }
401                }
402                return (T) bean;
403        }
404
405        @Override
406        public boolean containsBean(String name) {
407                String beanName = transformedBeanName(name);
408                if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
409                        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
410                }
411                // Not found -> check parent.
412                BeanFactory parentBeanFactory = getParentBeanFactory();
413                return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
414        }
415
416        @Override
417        public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
418                String beanName = transformedBeanName(name);
419
420                Object beanInstance = getSingleton(beanName, false);
421                if (beanInstance != null) {
422                        if (beanInstance instanceof FactoryBean) {
423                                return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton());
424                        }
425                        else {
426                                return !BeanFactoryUtils.isFactoryDereference(name);
427                        }
428                }
429
430                // No singleton instance found -> check bean definition.
431                BeanFactory parentBeanFactory = getParentBeanFactory();
432                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
433                        // No bean definition found in this factory -> delegate to parent.
434                        return parentBeanFactory.isSingleton(originalBeanName(name));
435                }
436
437                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
438
439                // In case of FactoryBean, return singleton status of created object if not a dereference.
440                if (mbd.isSingleton()) {
441                        if (isFactoryBean(beanName, mbd)) {
442                                if (BeanFactoryUtils.isFactoryDereference(name)) {
443                                        return true;
444                                }
445                                FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
446                                return factoryBean.isSingleton();
447                        }
448                        else {
449                                return !BeanFactoryUtils.isFactoryDereference(name);
450                        }
451                }
452                else {
453                        return false;
454                }
455        }
456
457        @Override
458        public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
459                String beanName = transformedBeanName(name);
460
461                BeanFactory parentBeanFactory = getParentBeanFactory();
462                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
463                        // No bean definition found in this factory -> delegate to parent.
464                        return parentBeanFactory.isPrototype(originalBeanName(name));
465                }
466
467                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
468                if (mbd.isPrototype()) {
469                        // In case of FactoryBean, return singleton status of created object if not a dereference.
470                        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd));
471                }
472
473                // Singleton or scoped - not a prototype.
474                // However, FactoryBean may still produce a prototype object...
475                if (BeanFactoryUtils.isFactoryDereference(name)) {
476                        return false;
477                }
478                if (isFactoryBean(beanName, mbd)) {
479                        FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
480                        if (System.getSecurityManager() != null) {
481                                return AccessController.doPrivileged(
482                                                (PrivilegedAction<Boolean>) () ->
483                                                                ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
484                                                                                !fb.isSingleton()),
485                                                getAccessControlContext());
486                        }
487                        else {
488                                return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
489                                                !fb.isSingleton());
490                        }
491                }
492                else {
493                        return false;
494                }
495        }
496
497        @Override
498        public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
499                return isTypeMatch(name, typeToMatch, true);
500        }
501
502        /**
503         * Internal extended variant of {@link #isTypeMatch(String, ResolvableType)}
504         * to check whether the bean with the given name matches the specified type. Allow
505         * additional constraints to be applied to ensure that beans are not created early.
506         * @param name the name of the bean to query
507         * @param typeToMatch the type to match against (as a
508         * {@code ResolvableType})
509         * @return {@code true} if the bean type matches, {@code false} if it
510         * doesn't match or cannot be determined yet
511         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
512         * @since 5.2
513         * @see #getBean
514         * @see #getType
515         */
516        protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
517                        throws NoSuchBeanDefinitionException {
518
519                String beanName = transformedBeanName(name);
520                boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);
521
522                // Check manually registered singletons.
523                Object beanInstance = getSingleton(beanName, false);
524                if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
525                        if (beanInstance instanceof FactoryBean) {
526                                if (!isFactoryDereference) {
527                                        Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
528                                        return (type != null && typeToMatch.isAssignableFrom(type));
529                                }
530                                else {
531                                        return typeToMatch.isInstance(beanInstance);
532                                }
533                        }
534                        else if (!isFactoryDereference) {
535                                if (typeToMatch.isInstance(beanInstance)) {
536                                        // Direct match for exposed instance?
537                                        return true;
538                                }
539                                else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
540                                        // Generics potentially only match on the target class, not on the proxy...
541                                        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
542                                        Class<?> targetType = mbd.getTargetType();
543                                        if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
544                                                // Check raw class match as well, making sure it's exposed on the proxy.
545                                                Class<?> classToMatch = typeToMatch.resolve();
546                                                if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
547                                                        return false;
548                                                }
549                                                if (typeToMatch.isAssignableFrom(targetType)) {
550                                                        return true;
551                                                }
552                                        }
553                                        ResolvableType resolvableType = mbd.targetType;
554                                        if (resolvableType == null) {
555                                                resolvableType = mbd.factoryMethodReturnType;
556                                        }
557                                        return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
558                                }
559                        }
560                        return false;
561                }
562                else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
563                        // null instance registered
564                        return false;
565                }
566
567                // No singleton instance found -> check bean definition.
568                BeanFactory parentBeanFactory = getParentBeanFactory();
569                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
570                        // No bean definition found in this factory -> delegate to parent.
571                        return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);
572                }
573
574                // Retrieve corresponding bean definition.
575                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
576                BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
577
578                // Setup the types that we want to match against
579                Class<?> classToMatch = typeToMatch.resolve();
580                if (classToMatch == null) {
581                        classToMatch = FactoryBean.class;
582                }
583                Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
584                                new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});
585
586
587                // Attempt to predict the bean type
588                Class<?> predictedType = null;
589
590                // We're looking for a regular reference but we're a factory bean that has
591                // a decorated bean definition. The target bean should be the same type
592                // as FactoryBean would ultimately return.
593                if (!isFactoryDereference && dbd != null && isFactoryBean(beanName, mbd)) {
594                        // We should only attempt if the user explicitly set lazy-init to true
595                        // and we know the merged bean definition is for a factory bean.
596                        if (!mbd.isLazyInit() || allowFactoryBeanInit) {
597                                RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
598                                Class<?> targetType = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
599                                if (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) {
600                                        predictedType = targetType;
601                                }
602                        }
603                }
604
605                // If we couldn't use the target type, try regular prediction.
606                if (predictedType == null) {
607                        predictedType = predictBeanType(beanName, mbd, typesToMatch);
608                        if (predictedType == null) {
609                                return false;
610                        }
611                }
612
613                // Attempt to get the actual ResolvableType for the bean.
614                ResolvableType beanType = null;
615
616                // If it's a FactoryBean, we want to look at what it creates, not the factory class.
617                if (FactoryBean.class.isAssignableFrom(predictedType)) {
618                        if (beanInstance == null && !isFactoryDereference) {
619                                beanType = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit);
620                                predictedType = beanType.resolve();
621                                if (predictedType == null) {
622                                        return false;
623                                }
624                        }
625                }
626                else if (isFactoryDereference) {
627                        // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
628                        // type but we nevertheless are being asked to dereference a FactoryBean...
629                        // Let's check the original bean class and proceed with it if it is a FactoryBean.
630                        predictedType = predictBeanType(beanName, mbd, FactoryBean.class);
631                        if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) {
632                                return false;
633                        }
634                }
635
636                // We don't have an exact type but if bean definition target type or the factory
637                // method return type matches the predicted type then we can use that.
638                if (beanType == null) {
639                        ResolvableType definedType = mbd.targetType;
640                        if (definedType == null) {
641                                definedType = mbd.factoryMethodReturnType;
642                        }
643                        if (definedType != null && definedType.resolve() == predictedType) {
644                                beanType = definedType;
645                        }
646                }
647
648                // If we have a bean type use it so that generics are considered
649                if (beanType != null) {
650                        return typeToMatch.isAssignableFrom(beanType);
651                }
652
653                // If we don't have a bean type, fallback to the predicted type
654                return typeToMatch.isAssignableFrom(predictedType);
655        }
656
657        @Override
658        public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
659                return isTypeMatch(name, ResolvableType.forRawClass(typeToMatch));
660        }
661
662        @Override
663        @Nullable
664        public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
665                return getType(name, true);
666        }
667
668        @Override
669        @Nullable
670        public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
671                String beanName = transformedBeanName(name);
672
673                // Check manually registered singletons.
674                Object beanInstance = getSingleton(beanName, false);
675                if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
676                        if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
677                                return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
678                        }
679                        else {
680                                return beanInstance.getClass();
681                        }
682                }
683
684                // No singleton instance found -> check bean definition.
685                BeanFactory parentBeanFactory = getParentBeanFactory();
686                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
687                        // No bean definition found in this factory -> delegate to parent.
688                        return parentBeanFactory.getType(originalBeanName(name));
689                }
690
691                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
692
693                // Check decorated bean definition, if any: We assume it'll be easier
694                // to determine the decorated bean's type than the proxy's type.
695                BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
696                if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
697                        RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
698                        Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
699                        if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
700                                return targetClass;
701                        }
702                }
703
704                Class<?> beanClass = predictBeanType(beanName, mbd);
705
706                // Check bean class whether we're dealing with a FactoryBean.
707                if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
708                        if (!BeanFactoryUtils.isFactoryDereference(name)) {
709                                // If it's a FactoryBean, we want to look at what it creates, not at the factory class.
710                                return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
711                        }
712                        else {
713                                return beanClass;
714                        }
715                }
716                else {
717                        return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
718                }
719        }
720
721        @Override
722        public String[] getAliases(String name) {
723                String beanName = transformedBeanName(name);
724                List<String> aliases = new ArrayList<>();
725                boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
726                String fullBeanName = beanName;
727                if (factoryPrefix) {
728                        fullBeanName = FACTORY_BEAN_PREFIX + beanName;
729                }
730                if (!fullBeanName.equals(name)) {
731                        aliases.add(fullBeanName);
732                }
733                String[] retrievedAliases = super.getAliases(beanName);
734                String prefix = factoryPrefix ? FACTORY_BEAN_PREFIX : "";
735                for (String retrievedAlias : retrievedAliases) {
736                        String alias = prefix + retrievedAlias;
737                        if (!alias.equals(name)) {
738                                aliases.add(alias);
739                        }
740                }
741                if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
742                        BeanFactory parentBeanFactory = getParentBeanFactory();
743                        if (parentBeanFactory != null) {
744                                aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName)));
745                        }
746                }
747                return StringUtils.toStringArray(aliases);
748        }
749
750
751        //---------------------------------------------------------------------
752        // Implementation of HierarchicalBeanFactory interface
753        //---------------------------------------------------------------------
754
755        @Override
756        @Nullable
757        public BeanFactory getParentBeanFactory() {
758                return this.parentBeanFactory;
759        }
760
761        @Override
762        public boolean containsLocalBean(String name) {
763                String beanName = transformedBeanName(name);
764                return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
765                                (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
766        }
767
768
769        //---------------------------------------------------------------------
770        // Implementation of ConfigurableBeanFactory interface
771        //---------------------------------------------------------------------
772
773        @Override
774        public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
775                if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
776                        throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
777                }
778                if (this == parentBeanFactory) {
779                        throw new IllegalStateException("Cannot set parent bean factory to self");
780                }
781                this.parentBeanFactory = parentBeanFactory;
782        }
783
784        @Override
785        public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
786                this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
787        }
788
789        @Override
790        @Nullable
791        public ClassLoader getBeanClassLoader() {
792                return this.beanClassLoader;
793        }
794
795        @Override
796        public void setTempClassLoader(@Nullable ClassLoader tempClassLoader) {
797                this.tempClassLoader = tempClassLoader;
798        }
799
800        @Override
801        @Nullable
802        public ClassLoader getTempClassLoader() {
803                return this.tempClassLoader;
804        }
805
806        @Override
807        public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
808                this.cacheBeanMetadata = cacheBeanMetadata;
809        }
810
811        @Override
812        public boolean isCacheBeanMetadata() {
813                return this.cacheBeanMetadata;
814        }
815
816        @Override
817        public void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver) {
818                this.beanExpressionResolver = resolver;
819        }
820
821        @Override
822        @Nullable
823        public BeanExpressionResolver getBeanExpressionResolver() {
824                return this.beanExpressionResolver;
825        }
826
827        @Override
828        public void setConversionService(@Nullable ConversionService conversionService) {
829                this.conversionService = conversionService;
830        }
831
832        @Override
833        @Nullable
834        public ConversionService getConversionService() {
835                return this.conversionService;
836        }
837
838        @Override
839        public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
840                Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
841                this.propertyEditorRegistrars.add(registrar);
842        }
843
844        /**
845         * Return the set of PropertyEditorRegistrars.
846         */
847        public Set<PropertyEditorRegistrar> getPropertyEditorRegistrars() {
848                return this.propertyEditorRegistrars;
849        }
850
851        @Override
852        public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
853                Assert.notNull(requiredType, "Required type must not be null");
854                Assert.notNull(propertyEditorClass, "PropertyEditor class must not be null");
855                this.customEditors.put(requiredType, propertyEditorClass);
856        }
857
858        @Override
859        public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) {
860                registerCustomEditors(registry);
861        }
862
863        /**
864         * Return the map of custom editors, with Classes as keys and PropertyEditor classes as values.
865         */
866        public Map<Class<?>, Class<? extends PropertyEditor>> getCustomEditors() {
867                return this.customEditors;
868        }
869
870        @Override
871        public void setTypeConverter(TypeConverter typeConverter) {
872                this.typeConverter = typeConverter;
873        }
874
875        /**
876         * Return the custom TypeConverter to use, if any.
877         * @return the custom TypeConverter, or {@code null} if none specified
878         */
879        @Nullable
880        protected TypeConverter getCustomTypeConverter() {
881                return this.typeConverter;
882        }
883
884        @Override
885        public TypeConverter getTypeConverter() {
886                TypeConverter customConverter = getCustomTypeConverter();
887                if (customConverter != null) {
888                        return customConverter;
889                }
890                else {
891                        // Build default TypeConverter, registering custom editors.
892                        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
893                        typeConverter.setConversionService(getConversionService());
894                        registerCustomEditors(typeConverter);
895                        return typeConverter;
896                }
897        }
898
899        @Override
900        public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
901                Assert.notNull(valueResolver, "StringValueResolver must not be null");
902                this.embeddedValueResolvers.add(valueResolver);
903        }
904
905        @Override
906        public boolean hasEmbeddedValueResolver() {
907                return !this.embeddedValueResolvers.isEmpty();
908        }
909
910        @Override
911        @Nullable
912        public String resolveEmbeddedValue(@Nullable String value) {
913                if (value == null) {
914                        return null;
915                }
916                String result = value;
917                for (StringValueResolver resolver : this.embeddedValueResolvers) {
918                        result = resolver.resolveStringValue(result);
919                        if (result == null) {
920                                return null;
921                        }
922                }
923                return result;
924        }
925
926        @Override
927        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
928                Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
929                // Remove from old position, if any
930                this.beanPostProcessors.remove(beanPostProcessor);
931                // Track whether it is instantiation/destruction aware
932                if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
933                        this.hasInstantiationAwareBeanPostProcessors = true;
934                }
935                if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
936                        this.hasDestructionAwareBeanPostProcessors = true;
937                }
938                // Add to end of list
939                this.beanPostProcessors.add(beanPostProcessor);
940        }
941
942        @Override
943        public int getBeanPostProcessorCount() {
944                return this.beanPostProcessors.size();
945        }
946
947        /**
948         * Return the list of BeanPostProcessors that will get applied
949         * to beans created with this factory.
950         */
951        public List<BeanPostProcessor> getBeanPostProcessors() {
952                return this.beanPostProcessors;
953        }
954
955        /**
956         * Return whether this factory holds a InstantiationAwareBeanPostProcessor
957         * that will get applied to singleton beans on creation.
958         * @see #addBeanPostProcessor
959         * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
960         */
961        protected boolean hasInstantiationAwareBeanPostProcessors() {
962                return this.hasInstantiationAwareBeanPostProcessors;
963        }
964
965        /**
966         * Return whether this factory holds a DestructionAwareBeanPostProcessor
967         * that will get applied to singleton beans on shutdown.
968         * @see #addBeanPostProcessor
969         * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
970         */
971        protected boolean hasDestructionAwareBeanPostProcessors() {
972                return this.hasDestructionAwareBeanPostProcessors;
973        }
974
975        @Override
976        public void registerScope(String scopeName, Scope scope) {
977                Assert.notNull(scopeName, "Scope identifier must not be null");
978                Assert.notNull(scope, "Scope must not be null");
979                if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
980                        throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
981                }
982                Scope previous = this.scopes.put(scopeName, scope);
983                if (previous != null && previous != scope) {
984                        if (logger.isDebugEnabled()) {
985                                logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
986                        }
987                }
988                else {
989                        if (logger.isTraceEnabled()) {
990                                logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
991                        }
992                }
993        }
994
995        @Override
996        public String[] getRegisteredScopeNames() {
997                return StringUtils.toStringArray(this.scopes.keySet());
998        }
999
1000        @Override
1001        @Nullable
1002        public Scope getRegisteredScope(String scopeName) {
1003                Assert.notNull(scopeName, "Scope identifier must not be null");
1004                return this.scopes.get(scopeName);
1005        }
1006
1007        /**
1008         * Set the security context provider for this bean factory. If a security manager
1009         * is set, interaction with the user code will be executed using the privileged
1010         * of the provided security context.
1011         */
1012        public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
1013                this.securityContextProvider = securityProvider;
1014        }
1015
1016        /**
1017         * Delegate the creation of the access control context to the
1018         * {@link #setSecurityContextProvider SecurityContextProvider}.
1019         */
1020        @Override
1021        public AccessControlContext getAccessControlContext() {
1022                return (this.securityContextProvider != null ?
1023                                this.securityContextProvider.getAccessControlContext() :
1024                                AccessController.getContext());
1025        }
1026
1027        @Override
1028        public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
1029                Assert.notNull(otherFactory, "BeanFactory must not be null");
1030                setBeanClassLoader(otherFactory.getBeanClassLoader());
1031                setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
1032                setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
1033                setConversionService(otherFactory.getConversionService());
1034                if (otherFactory instanceof AbstractBeanFactory) {
1035                        AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
1036                        this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
1037                        this.customEditors.putAll(otherAbstractFactory.customEditors);
1038                        this.typeConverter = otherAbstractFactory.typeConverter;
1039                        this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
1040                        this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
1041                                        otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
1042                        this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
1043                                        otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
1044                        this.scopes.putAll(otherAbstractFactory.scopes);
1045                        this.securityContextProvider = otherAbstractFactory.securityContextProvider;
1046                }
1047                else {
1048                        setTypeConverter(otherFactory.getTypeConverter());
1049                        String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
1050                        for (String scopeName : otherScopeNames) {
1051                                this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
1052                        }
1053                }
1054        }
1055
1056        /**
1057         * Return a 'merged' BeanDefinition for the given bean name,
1058         * merging a child bean definition with its parent if necessary.
1059         * <p>This {@code getMergedBeanDefinition} considers bean definition
1060         * in ancestors as well.
1061         * @param name the name of the bean to retrieve the merged definition for
1062         * (may be an alias)
1063         * @return a (potentially merged) RootBeanDefinition for the given bean
1064         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
1065         * @throws BeanDefinitionStoreException in case of an invalid bean definition
1066         */
1067        @Override
1068        public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
1069                String beanName = transformedBeanName(name);
1070                // Efficiently check whether bean definition exists in this factory.
1071                if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
1072                        return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
1073                }
1074                // Resolve merged bean definition locally.
1075                return getMergedLocalBeanDefinition(beanName);
1076        }
1077
1078        @Override
1079        public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
1080                String beanName = transformedBeanName(name);
1081                Object beanInstance = getSingleton(beanName, false);
1082                if (beanInstance != null) {
1083                        return (beanInstance instanceof FactoryBean);
1084                }
1085                // No singleton instance found -> check bean definition.
1086                if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
1087                        // No bean definition found in this factory -> delegate to parent.
1088                        return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
1089                }
1090                return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
1091        }
1092
1093        @Override
1094        public boolean isActuallyInCreation(String beanName) {
1095                return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName));
1096        }
1097
1098        /**
1099         * Return whether the specified prototype bean is currently in creation
1100         * (within the current thread).
1101         * @param beanName the name of the bean
1102         */
1103        protected boolean isPrototypeCurrentlyInCreation(String beanName) {
1104                Object curVal = this.prototypesCurrentlyInCreation.get();
1105                return (curVal != null &&
1106                                (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
1107        }
1108
1109        /**
1110         * Callback before prototype creation.
1111         * <p>The default implementation register the prototype as currently in creation.
1112         * @param beanName the name of the prototype about to be created
1113         * @see #isPrototypeCurrentlyInCreation
1114         */
1115        @SuppressWarnings("unchecked")
1116        protected void beforePrototypeCreation(String beanName) {
1117                Object curVal = this.prototypesCurrentlyInCreation.get();
1118                if (curVal == null) {
1119                        this.prototypesCurrentlyInCreation.set(beanName);
1120                }
1121                else if (curVal instanceof String) {
1122                        Set<String> beanNameSet = new HashSet<>(2);
1123                        beanNameSet.add((String) curVal);
1124                        beanNameSet.add(beanName);
1125                        this.prototypesCurrentlyInCreation.set(beanNameSet);
1126                }
1127                else {
1128                        Set<String> beanNameSet = (Set<String>) curVal;
1129                        beanNameSet.add(beanName);
1130                }
1131        }
1132
1133        /**
1134         * Callback after prototype creation.
1135         * <p>The default implementation marks the prototype as not in creation anymore.
1136         * @param beanName the name of the prototype that has been created
1137         * @see #isPrototypeCurrentlyInCreation
1138         */
1139        @SuppressWarnings("unchecked")
1140        protected void afterPrototypeCreation(String beanName) {
1141                Object curVal = this.prototypesCurrentlyInCreation.get();
1142                if (curVal instanceof String) {
1143                        this.prototypesCurrentlyInCreation.remove();
1144                }
1145                else if (curVal instanceof Set) {
1146                        Set<String> beanNameSet = (Set<String>) curVal;
1147                        beanNameSet.remove(beanName);
1148                        if (beanNameSet.isEmpty()) {
1149                                this.prototypesCurrentlyInCreation.remove();
1150                        }
1151                }
1152        }
1153
1154        @Override
1155        public void destroyBean(String beanName, Object beanInstance) {
1156                destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
1157        }
1158
1159        /**
1160         * Destroy the given bean instance (usually a prototype instance
1161         * obtained from this factory) according to the given bean definition.
1162         * @param beanName the name of the bean definition
1163         * @param bean the bean instance to destroy
1164         * @param mbd the merged bean definition
1165         */
1166        protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
1167                new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
1168        }
1169
1170        @Override
1171        public void destroyScopedBean(String beanName) {
1172                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
1173                if (mbd.isSingleton() || mbd.isPrototype()) {
1174                        throw new IllegalArgumentException(
1175                                        "Bean name '" + beanName + "' does not correspond to an object in a mutable scope");
1176                }
1177                String scopeName = mbd.getScope();
1178                Scope scope = this.scopes.get(scopeName);
1179                if (scope == null) {
1180                        throw new IllegalStateException("No Scope SPI registered for scope name '" + scopeName + "'");
1181                }
1182                Object bean = scope.remove(beanName);
1183                if (bean != null) {
1184                        destroyBean(beanName, bean, mbd);
1185                }
1186        }
1187
1188
1189        //---------------------------------------------------------------------
1190        // Implementation methods
1191        //---------------------------------------------------------------------
1192
1193        /**
1194         * Return the bean name, stripping out the factory dereference prefix if necessary,
1195         * and resolving aliases to canonical names.
1196         * @param name the user-specified name
1197         * @return the transformed bean name
1198         */
1199        protected String transformedBeanName(String name) {
1200                return canonicalName(BeanFactoryUtils.transformedBeanName(name));
1201        }
1202
1203        /**
1204         * Determine the original bean name, resolving locally defined aliases to canonical names.
1205         * @param name the user-specified name
1206         * @return the original bean name
1207         */
1208        protected String originalBeanName(String name) {
1209                String beanName = transformedBeanName(name);
1210                if (name.startsWith(FACTORY_BEAN_PREFIX)) {
1211                        beanName = FACTORY_BEAN_PREFIX + beanName;
1212                }
1213                return beanName;
1214        }
1215
1216        /**
1217         * Initialize the given BeanWrapper with the custom editors registered
1218         * with this factory. To be called for BeanWrappers that will create
1219         * and populate bean instances.
1220         * <p>The default implementation delegates to {@link #registerCustomEditors}.
1221         * Can be overridden in subclasses.
1222         * @param bw the BeanWrapper to initialize
1223         */
1224        protected void initBeanWrapper(BeanWrapper bw) {
1225                bw.setConversionService(getConversionService());
1226                registerCustomEditors(bw);
1227        }
1228
1229        /**
1230         * Initialize the given PropertyEditorRegistry with the custom editors
1231         * that have been registered with this BeanFactory.
1232         * <p>To be called for BeanWrappers that will create and populate bean
1233         * instances, and for SimpleTypeConverter used for constructor argument
1234         * and factory method type conversion.
1235         * @param registry the PropertyEditorRegistry to initialize
1236         */
1237        protected void registerCustomEditors(PropertyEditorRegistry registry) {
1238                PropertyEditorRegistrySupport registrySupport =
1239                                (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
1240                if (registrySupport != null) {
1241                        registrySupport.useConfigValueEditors();
1242                }
1243                if (!this.propertyEditorRegistrars.isEmpty()) {
1244                        for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
1245                                try {
1246                                        registrar.registerCustomEditors(registry);
1247                                }
1248                                catch (BeanCreationException ex) {
1249                                        Throwable rootCause = ex.getMostSpecificCause();
1250                                        if (rootCause instanceof BeanCurrentlyInCreationException) {
1251                                                BeanCreationException bce = (BeanCreationException) rootCause;
1252                                                String bceBeanName = bce.getBeanName();
1253                                                if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
1254                                                        if (logger.isDebugEnabled()) {
1255                                                                logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
1256                                                                                "] failed because it tried to obtain currently created bean '" +
1257                                                                                ex.getBeanName() + "': " + ex.getMessage());
1258                                                        }
1259                                                        onSuppressedException(ex);
1260                                                        continue;
1261                                                }
1262                                        }
1263                                        throw ex;
1264                                }
1265                        }
1266                }
1267                if (!this.customEditors.isEmpty()) {
1268                        this.customEditors.forEach((requiredType, editorClass) ->
1269                                        registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
1270                }
1271        }
1272
1273
1274        /**
1275         * Return a merged RootBeanDefinition, traversing the parent bean definition
1276         * if the specified bean corresponds to a child bean definition.
1277         * @param beanName the name of the bean to retrieve the merged definition for
1278         * @return a (potentially merged) RootBeanDefinition for the given bean
1279         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
1280         * @throws BeanDefinitionStoreException in case of an invalid bean definition
1281         */
1282        protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
1283                // Quick check on the concurrent map first, with minimal locking.
1284                RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
1285                if (mbd != null && !mbd.stale) {
1286                        return mbd;
1287                }
1288                return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
1289        }
1290
1291        /**
1292         * Return a RootBeanDefinition for the given top-level bean, by merging with
1293         * the parent if the given bean's definition is a child bean definition.
1294         * @param beanName the name of the bean definition
1295         * @param bd the original bean definition (Root/ChildBeanDefinition)
1296         * @return a (potentially merged) RootBeanDefinition for the given bean
1297         * @throws BeanDefinitionStoreException in case of an invalid bean definition
1298         */
1299        protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
1300                        throws BeanDefinitionStoreException {
1301
1302                return getMergedBeanDefinition(beanName, bd, null);
1303        }
1304
1305        /**
1306         * Return a RootBeanDefinition for the given bean, by merging with the
1307         * parent if the given bean's definition is a child bean definition.
1308         * @param beanName the name of the bean definition
1309         * @param bd the original bean definition (Root/ChildBeanDefinition)
1310         * @param containingBd the containing bean definition in case of inner bean,
1311         * or {@code null} in case of a top-level bean
1312         * @return a (potentially merged) RootBeanDefinition for the given bean
1313         * @throws BeanDefinitionStoreException in case of an invalid bean definition
1314         */
1315        protected RootBeanDefinition getMergedBeanDefinition(
1316                        String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
1317                        throws BeanDefinitionStoreException {
1318
1319                synchronized (this.mergedBeanDefinitions) {
1320                        RootBeanDefinition mbd = null;
1321                        RootBeanDefinition previous = null;
1322
1323                        // Check with full lock now in order to enforce the same merged instance.
1324                        if (containingBd == null) {
1325                                mbd = this.mergedBeanDefinitions.get(beanName);
1326                        }
1327
1328                        if (mbd == null || mbd.stale) {
1329                                previous = mbd;
1330                                if (bd.getParentName() == null) {
1331                                        // Use copy of given root bean definition.
1332                                        if (bd instanceof RootBeanDefinition) {
1333                                                mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
1334                                        }
1335                                        else {
1336                                                mbd = new RootBeanDefinition(bd);
1337                                        }
1338                                }
1339                                else {
1340                                        // Child bean definition: needs to be merged with parent.
1341                                        BeanDefinition pbd;
1342                                        try {
1343                                                String parentBeanName = transformedBeanName(bd.getParentName());
1344                                                if (!beanName.equals(parentBeanName)) {
1345                                                        pbd = getMergedBeanDefinition(parentBeanName);
1346                                                }
1347                                                else {
1348                                                        BeanFactory parent = getParentBeanFactory();
1349                                                        if (parent instanceof ConfigurableBeanFactory) {
1350                                                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
1351                                                        }
1352                                                        else {
1353                                                                throw new NoSuchBeanDefinitionException(parentBeanName,
1354                                                                                "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
1355                                                                                "': cannot be resolved without a ConfigurableBeanFactory parent");
1356                                                        }
1357                                                }
1358                                        }
1359                                        catch (NoSuchBeanDefinitionException ex) {
1360                                                throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
1361                                                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
1362                                        }
1363                                        // Deep copy with overridden values.
1364                                        mbd = new RootBeanDefinition(pbd);
1365                                        mbd.overrideFrom(bd);
1366                                }
1367
1368                                // Set default singleton scope, if not configured before.
1369                                if (!StringUtils.hasLength(mbd.getScope())) {
1370                                        mbd.setScope(SCOPE_SINGLETON);
1371                                }
1372
1373                                // A bean contained in a non-singleton bean cannot be a singleton itself.
1374                                // Let's correct this on the fly here, since this might be the result of
1375                                // parent-child merging for the outer bean, in which case the original inner bean
1376                                // definition will not have inherited the merged outer bean's singleton status.
1377                                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
1378                                        mbd.setScope(containingBd.getScope());
1379                                }
1380
1381                                // Cache the merged bean definition for the time being
1382                                // (it might still get re-merged later on in order to pick up metadata changes)
1383                                if (containingBd == null && isCacheBeanMetadata()) {
1384                                        this.mergedBeanDefinitions.put(beanName, mbd);
1385                                }
1386                        }
1387                        if (previous != null) {
1388                                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
1389                        }
1390                        return mbd;
1391                }
1392        }
1393
1394        private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
1395                if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
1396                                ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
1397                                ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
1398                        ResolvableType targetType = mbd.targetType;
1399                        ResolvableType previousTargetType = previous.targetType;
1400                        if (targetType == null || targetType.equals(previousTargetType)) {
1401                                mbd.targetType = previousTargetType;
1402                                mbd.isFactoryBean = previous.isFactoryBean;
1403                                mbd.resolvedTargetType = previous.resolvedTargetType;
1404                                mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
1405                                mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
1406                        }
1407                }
1408        }
1409
1410        /**
1411         * Check the given merged bean definition,
1412         * potentially throwing validation exceptions.
1413         * @param mbd the merged bean definition to check
1414         * @param beanName the name of the bean
1415         * @param args the arguments for bean creation, if any
1416         * @throws BeanDefinitionStoreException in case of validation failure
1417         */
1418        protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
1419                        throws BeanDefinitionStoreException {
1420
1421                if (mbd.isAbstract()) {
1422                        throw new BeanIsAbstractException(beanName);
1423                }
1424        }
1425
1426        /**
1427         * Remove the merged bean definition for the specified bean,
1428         * recreating it on next access.
1429         * @param beanName the bean name to clear the merged definition for
1430         */
1431        protected void clearMergedBeanDefinition(String beanName) {
1432                RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
1433                if (bd != null) {
1434                        bd.stale = true;
1435                }
1436        }
1437
1438        /**
1439         * Clear the merged bean definition cache, removing entries for beans
1440         * which are not considered eligible for full metadata caching yet.
1441         * <p>Typically triggered after changes to the original bean definitions,
1442         * e.g. after applying a {@code BeanFactoryPostProcessor}. Note that metadata
1443         * for beans which have already been created at this point will be kept around.
1444         * @since 4.2
1445         */
1446        public void clearMetadataCache() {
1447                this.mergedBeanDefinitions.forEach((beanName, bd) -> {
1448                        if (!isBeanEligibleForMetadataCaching(beanName)) {
1449                                bd.stale = true;
1450                        }
1451                });
1452        }
1453
1454        /**
1455         * Resolve the bean class for the specified bean definition,
1456         * resolving a bean class name into a Class reference (if necessary)
1457         * and storing the resolved Class in the bean definition for further use.
1458         * @param mbd the merged bean definition to determine the class for
1459         * @param beanName the name of the bean (for error handling purposes)
1460         * @param typesToMatch the types to match in case of internal type matching purposes
1461         * (also signals that the returned {@code Class} will never be exposed to application code)
1462         * @return the resolved bean class (or {@code null} if none)
1463         * @throws CannotLoadBeanClassException if we failed to load the class
1464         */
1465        @Nullable
1466        protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
1467                        throws CannotLoadBeanClassException {
1468
1469                try {
1470                        if (mbd.hasBeanClass()) {
1471                                return mbd.getBeanClass();
1472                        }
1473                        if (System.getSecurityManager() != null) {
1474                                return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
1475                                                () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
1476                        }
1477                        else {
1478                                return doResolveBeanClass(mbd, typesToMatch);
1479                        }
1480                }
1481                catch (PrivilegedActionException pae) {
1482                        ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
1483                        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
1484                }
1485                catch (ClassNotFoundException ex) {
1486                        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
1487                }
1488                catch (LinkageError err) {
1489                        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
1490                }
1491        }
1492
1493        @Nullable
1494        private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
1495                        throws ClassNotFoundException {
1496
1497                ClassLoader beanClassLoader = getBeanClassLoader();
1498                ClassLoader dynamicLoader = beanClassLoader;
1499                boolean freshResolve = false;
1500
1501                if (!ObjectUtils.isEmpty(typesToMatch)) {
1502                        // When just doing type checks (i.e. not creating an actual instance yet),
1503                        // use the specified temporary class loader (e.g. in a weaving scenario).
1504                        ClassLoader tempClassLoader = getTempClassLoader();
1505                        if (tempClassLoader != null) {
1506                                dynamicLoader = tempClassLoader;
1507                                freshResolve = true;
1508                                if (tempClassLoader instanceof DecoratingClassLoader) {
1509                                        DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
1510                                        for (Class<?> typeToMatch : typesToMatch) {
1511                                                dcl.excludeClass(typeToMatch.getName());
1512                                        }
1513                                }
1514                        }
1515                }
1516
1517                String className = mbd.getBeanClassName();
1518                if (className != null) {
1519                        Object evaluated = evaluateBeanDefinitionString(className, mbd);
1520                        if (!className.equals(evaluated)) {
1521                                // A dynamically resolved expression, supported as of 4.2...
1522                                if (evaluated instanceof Class) {
1523                                        return (Class<?>) evaluated;
1524                                }
1525                                else if (evaluated instanceof String) {
1526                                        className = (String) evaluated;
1527                                        freshResolve = true;
1528                                }
1529                                else {
1530                                        throw new IllegalStateException("Invalid class name expression result: " + evaluated);
1531                                }
1532                        }
1533                        if (freshResolve) {
1534                                // When resolving against a temporary class loader, exit early in order
1535                                // to avoid storing the resolved Class in the bean definition.
1536                                if (dynamicLoader != null) {
1537                                        try {
1538                                                return dynamicLoader.loadClass(className);
1539                                        }
1540                                        catch (ClassNotFoundException ex) {
1541                                                if (logger.isTraceEnabled()) {
1542                                                        logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
1543                                                }
1544                                        }
1545                                }
1546                                return ClassUtils.forName(className, dynamicLoader);
1547                        }
1548                }
1549
1550                // Resolve regularly, caching the result in the BeanDefinition...
1551                return mbd.resolveBeanClass(beanClassLoader);
1552        }
1553
1554        /**
1555         * Evaluate the given String as contained in a bean definition,
1556         * potentially resolving it as an expression.
1557         * @param value the value to check
1558         * @param beanDefinition the bean definition that the value comes from
1559         * @return the resolved value
1560         * @see #setBeanExpressionResolver
1561         */
1562        @Nullable
1563        protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
1564                if (this.beanExpressionResolver == null) {
1565                        return value;
1566                }
1567
1568                Scope scope = null;
1569                if (beanDefinition != null) {
1570                        String scopeName = beanDefinition.getScope();
1571                        if (scopeName != null) {
1572                                scope = getRegisteredScope(scopeName);
1573                        }
1574                }
1575                return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
1576        }
1577
1578
1579        /**
1580         * Predict the eventual bean type (of the processed bean instance) for the
1581         * specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
1582         * Does not need to handle FactoryBeans specifically, since it is only
1583         * supposed to operate on the raw bean type.
1584         * <p>This implementation is simplistic in that it is not able to
1585         * handle factory methods and InstantiationAwareBeanPostProcessors.
1586         * It only predicts the bean type correctly for a standard bean.
1587         * To be overridden in subclasses, applying more sophisticated type detection.
1588         * @param beanName the name of the bean
1589         * @param mbd the merged bean definition to determine the type for
1590         * @param typesToMatch the types to match in case of internal type matching purposes
1591         * (also signals that the returned {@code Class} will never be exposed to application code)
1592         * @return the type of the bean, or {@code null} if not predictable
1593         */
1594        @Nullable
1595        protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
1596                Class<?> targetType = mbd.getTargetType();
1597                if (targetType != null) {
1598                        return targetType;
1599                }
1600                if (mbd.getFactoryMethodName() != null) {
1601                        return null;
1602                }
1603                return resolveBeanClass(mbd, beanName, typesToMatch);
1604        }
1605
1606        /**
1607         * Check whether the given bean is defined as a {@link FactoryBean}.
1608         * @param beanName the name of the bean
1609         * @param mbd the corresponding bean definition
1610         */
1611        protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
1612                Boolean result = mbd.isFactoryBean;
1613                if (result == null) {
1614                        Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
1615                        result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
1616                        mbd.isFactoryBean = result;
1617                }
1618                return result;
1619        }
1620
1621        /**
1622         * Determine the bean type for the given FactoryBean definition, as far as possible.
1623         * Only called if there is no singleton instance registered for the target bean
1624         * already. The implementation is allowed to instantiate the target factory bean if
1625         * {@code allowInit} is {@code true} and the type cannot be determined another way;
1626         * otherwise it is restricted to introspecting signatures and related metadata.
1627         * <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition
1628         * and {@code allowInit} is {@code true}, the default implementation will create
1629         * the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
1630         * Subclasses are encouraged to optimize this, typically by inspecting the generic
1631         * signature of the factory bean class or the factory method that creates it.
1632         * If subclasses do instantiate the FactoryBean, they should consider trying the
1633         * {@code getObjectType} method without fully populating the bean. If this fails,
1634         * a full FactoryBean creation as performed by this implementation should be used
1635         * as fallback.
1636         * @param beanName the name of the bean
1637         * @param mbd the merged bean definition for the bean
1638         * @param allowInit if initialization of the FactoryBean is permitted if the type
1639         * cannot be determined another way
1640         * @return the type for the bean if determinable, otherwise {@code ResolvableType.NONE}
1641         * @since 5.2
1642         * @see org.springframework.beans.factory.FactoryBean#getObjectType()
1643         * @see #getBean(String)
1644         */
1645        protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefinition mbd, boolean allowInit) {
1646                ResolvableType result = getTypeForFactoryBeanFromAttributes(mbd);
1647                if (result != ResolvableType.NONE) {
1648                        return result;
1649                }
1650
1651                if (allowInit && mbd.isSingleton()) {
1652                        try {
1653                                FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
1654                                Class<?> objectType = getTypeForFactoryBean(factoryBean);
1655                                return (objectType != null ? ResolvableType.forClass(objectType) : ResolvableType.NONE);
1656                        }
1657                        catch (BeanCreationException ex) {
1658                                if (ex.contains(BeanCurrentlyInCreationException.class)) {
1659                                        logger.trace(LogMessage.format("Bean currently in creation on FactoryBean type check: %s", ex));
1660                                }
1661                                else if (mbd.isLazyInit()) {
1662                                        logger.trace(LogMessage.format("Bean creation exception on lazy FactoryBean type check: %s", ex));
1663                                }
1664                                else {
1665                                        logger.debug(LogMessage.format("Bean creation exception on eager FactoryBean type check: %s", ex));
1666                                }
1667                                onSuppressedException(ex);
1668                        }
1669                }
1670                return ResolvableType.NONE;
1671        }
1672
1673        /**
1674         * Determine the bean type for a FactoryBean by inspecting its attributes for a
1675         * {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} value.
1676         * @param attributes the attributes to inspect
1677         * @return a {@link ResolvableType} extracted from the attributes or
1678         * {@code ResolvableType.NONE}
1679         * @since 5.2
1680         */
1681        ResolvableType getTypeForFactoryBeanFromAttributes(AttributeAccessor attributes) {
1682                Object attribute = attributes.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
1683                if (attribute instanceof ResolvableType) {
1684                        return (ResolvableType) attribute;
1685                }
1686                if (attribute instanceof Class) {
1687                        return ResolvableType.forClass((Class<?>) attribute);
1688                }
1689                return ResolvableType.NONE;
1690        }
1691
1692        /**
1693         * Determine the bean type for the given FactoryBean definition, as far as possible.
1694         * Only called if there is no singleton instance registered for the target bean already.
1695         * <p>The default implementation creates the FactoryBean via {@code getBean}
1696         * to call its {@code getObjectType} method. Subclasses are encouraged to optimize
1697         * this, typically by just instantiating the FactoryBean but not populating it yet,
1698         * trying whether its {@code getObjectType} method already returns a type.
1699         * If no type found, a full FactoryBean creation as performed by this implementation
1700         * should be used as fallback.
1701         * @param beanName the name of the bean
1702         * @param mbd the merged bean definition for the bean
1703         * @return the type for the bean if determinable, or {@code null} otherwise
1704         * @see org.springframework.beans.factory.FactoryBean#getObjectType()
1705         * @see #getBean(String)
1706         * @deprecated since 5.2 in favor of {@link #getTypeForFactoryBean(String, RootBeanDefinition, boolean)}
1707         */
1708        @Nullable
1709        @Deprecated
1710        protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
1711                return getTypeForFactoryBean(beanName, mbd, true).resolve();
1712        }
1713
1714        /**
1715         * Mark the specified bean as already created (or about to be created).
1716         * <p>This allows the bean factory to optimize its caching for repeated
1717         * creation of the specified bean.
1718         * @param beanName the name of the bean
1719         */
1720        protected void markBeanAsCreated(String beanName) {
1721                if (!this.alreadyCreated.contains(beanName)) {
1722                        synchronized (this.mergedBeanDefinitions) {
1723                                if (!this.alreadyCreated.contains(beanName)) {
1724                                        // Let the bean definition get re-merged now that we're actually creating
1725                                        // the bean... just in case some of its metadata changed in the meantime.
1726                                        clearMergedBeanDefinition(beanName);
1727                                        this.alreadyCreated.add(beanName);
1728                                }
1729                        }
1730                }
1731        }
1732
1733        /**
1734         * Perform appropriate cleanup of cached metadata after bean creation failed.
1735         * @param beanName the name of the bean
1736         */
1737        protected void cleanupAfterBeanCreationFailure(String beanName) {
1738                synchronized (this.mergedBeanDefinitions) {
1739                        this.alreadyCreated.remove(beanName);
1740                }
1741        }
1742
1743        /**
1744         * Determine whether the specified bean is eligible for having
1745         * its bean definition metadata cached.
1746         * @param beanName the name of the bean
1747         * @return {@code true} if the bean's metadata may be cached
1748         * at this point already
1749         */
1750        protected boolean isBeanEligibleForMetadataCaching(String beanName) {
1751                return this.alreadyCreated.contains(beanName);
1752        }
1753
1754        /**
1755         * Remove the singleton instance (if any) for the given bean name,
1756         * but only if it hasn't been used for other purposes than type checking.
1757         * @param beanName the name of the bean
1758         * @return {@code true} if actually removed, {@code false} otherwise
1759         */
1760        protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
1761                if (!this.alreadyCreated.contains(beanName)) {
1762                        removeSingleton(beanName);
1763                        return true;
1764                }
1765                else {
1766                        return false;
1767                }
1768        }
1769
1770        /**
1771         * Check whether this factory's bean creation phase already started,
1772         * i.e. whether any bean has been marked as created in the meantime.
1773         * @since 4.2.2
1774         * @see #markBeanAsCreated
1775         */
1776        protected boolean hasBeanCreationStarted() {
1777                return !this.alreadyCreated.isEmpty();
1778        }
1779
1780        /**
1781         * Get the object for the given bean instance, either the bean
1782         * instance itself or its created object in case of a FactoryBean.
1783         * @param beanInstance the shared bean instance
1784         * @param name the name that may include factory dereference prefix
1785         * @param beanName the canonical bean name
1786         * @param mbd the merged bean definition
1787         * @return the object to expose for the bean
1788         */
1789        protected Object getObjectForBeanInstance(
1790                        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
1791
1792                // Don't let calling code try to dereference the factory if the bean isn't a factory.
1793                if (BeanFactoryUtils.isFactoryDereference(name)) {
1794                        if (beanInstance instanceof NullBean) {
1795                                return beanInstance;
1796                        }
1797                        if (!(beanInstance instanceof FactoryBean)) {
1798                                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
1799                        }
1800                        if (mbd != null) {
1801                                mbd.isFactoryBean = true;
1802                        }
1803                        return beanInstance;
1804                }
1805
1806                // Now we have the bean instance, which may be a normal bean or a FactoryBean.
1807                // If it's a FactoryBean, we use it to create a bean instance, unless the
1808                // caller actually wants a reference to the factory.
1809                if (!(beanInstance instanceof FactoryBean)) {
1810                        return beanInstance;
1811                }
1812
1813                Object object = null;
1814                if (mbd != null) {
1815                        mbd.isFactoryBean = true;
1816                }
1817                else {
1818                        object = getCachedObjectForFactoryBean(beanName);
1819                }
1820                if (object == null) {
1821                        // Return bean instance from factory.
1822                        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
1823                        // Caches object obtained from FactoryBean if it is a singleton.
1824                        if (mbd == null && containsBeanDefinition(beanName)) {
1825                                mbd = getMergedLocalBeanDefinition(beanName);
1826                        }
1827                        boolean synthetic = (mbd != null && mbd.isSynthetic());
1828                        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
1829                }
1830                return object;
1831        }
1832
1833        /**
1834         * Determine whether the given bean name is already in use within this factory,
1835         * i.e. whether there is a local bean or alias registered under this name or
1836         * an inner bean created with this name.
1837         * @param beanName the name to check
1838         */
1839        public boolean isBeanNameInUse(String beanName) {
1840                return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName);
1841        }
1842
1843        /**
1844         * Determine whether the given bean requires destruction on shutdown.
1845         * <p>The default implementation checks the DisposableBean interface as well as
1846         * a specified destroy method and registered DestructionAwareBeanPostProcessors.
1847         * @param bean the bean instance to check
1848         * @param mbd the corresponding bean definition
1849         * @see org.springframework.beans.factory.DisposableBean
1850         * @see AbstractBeanDefinition#getDestroyMethodName()
1851         * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
1852         */
1853        protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
1854                return (bean.getClass() != NullBean.class &&
1855                                (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
1856                                                DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
1857        }
1858
1859        /**
1860         * Add the given bean to the list of disposable beans in this factory,
1861         * registering its DisposableBean interface and/or the given destroy method
1862         * to be called on factory shutdown (if applicable). Only applies to singletons.
1863         * @param beanName the name of the bean
1864         * @param bean the bean instance
1865         * @param mbd the bean definition for the bean
1866         * @see RootBeanDefinition#isSingleton
1867         * @see RootBeanDefinition#getDependsOn
1868         * @see #registerDisposableBean
1869         * @see #registerDependentBean
1870         */
1871        protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
1872                AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
1873                if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
1874                        if (mbd.isSingleton()) {
1875                                // Register a DisposableBean implementation that performs all destruction
1876                                // work for the given bean: DestructionAwareBeanPostProcessors,
1877                                // DisposableBean interface, custom destroy method.
1878                                registerDisposableBean(beanName,
1879                                                new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
1880                        }
1881                        else {
1882                                // A bean with a custom scope...
1883                                Scope scope = this.scopes.get(mbd.getScope());
1884                                if (scope == null) {
1885                                        throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
1886                                }
1887                                scope.registerDestructionCallback(beanName,
1888                                                new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
1889                        }
1890                }
1891        }
1892
1893
1894        //---------------------------------------------------------------------
1895        // Abstract methods to be implemented by subclasses
1896        //---------------------------------------------------------------------
1897
1898        /**
1899         * Check if this bean factory contains a bean definition with the given name.
1900         * Does not consider any hierarchy this factory may participate in.
1901         * Invoked by {@code containsBean} when no cached singleton instance is found.
1902         * <p>Depending on the nature of the concrete bean factory implementation,
1903         * this operation might be expensive (for example, because of directory lookups
1904         * in external registries). However, for listable bean factories, this usually
1905         * just amounts to a local hash lookup: The operation is therefore part of the
1906         * public interface there. The same implementation can serve for both this
1907         * template method and the public interface method in that case.
1908         * @param beanName the name of the bean to look for
1909         * @return if this bean factory contains a bean definition with the given name
1910         * @see #containsBean
1911         * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
1912         */
1913        protected abstract boolean containsBeanDefinition(String beanName);
1914
1915        /**
1916         * Return the bean definition for the given bean name.
1917         * Subclasses should normally implement caching, as this method is invoked
1918         * by this class every time bean definition metadata is needed.
1919         * <p>Depending on the nature of the concrete bean factory implementation,
1920         * this operation might be expensive (for example, because of directory lookups
1921         * in external registries). However, for listable bean factories, this usually
1922         * just amounts to a local hash lookup: The operation is therefore part of the
1923         * public interface there. The same implementation can serve for both this
1924         * template method and the public interface method in that case.
1925         * @param beanName the name of the bean to find a definition for
1926         * @return the BeanDefinition for this prototype name (never {@code null})
1927         * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
1928         * if the bean definition cannot be resolved
1929         * @throws BeansException in case of errors
1930         * @see RootBeanDefinition
1931         * @see ChildBeanDefinition
1932         * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
1933         */
1934        protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
1935
1936        /**
1937         * Create a bean instance for the given merged bean definition (and arguments).
1938         * The bean definition will already have been merged with the parent definition
1939         * in case of a child definition.
1940         * <p>All bean retrieval methods delegate to this method for actual bean creation.
1941         * @param beanName the name of the bean
1942         * @param mbd the merged bean definition for the bean
1943         * @param args explicit arguments to use for constructor or factory method invocation
1944         * @return a new instance of the bean
1945         * @throws BeanCreationException if the bean could not be created
1946         */
1947        protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
1948                        throws BeanCreationException;
1949
1950}