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