Source Code Cross Referenced for AbstractBeanFactory.java in  » J2EE » spring-framework-2.0.6 » org » springframework » beans » factory » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.beans.factory.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.beans.factory.support;
0018:
0019:        import java.beans.PropertyEditor;
0020:        import java.util.ArrayList;
0021:        import java.util.Arrays;
0022:        import java.util.Collections;
0023:        import java.util.HashMap;
0024:        import java.util.HashSet;
0025:        import java.util.Iterator;
0026:        import java.util.List;
0027:        import java.util.Map;
0028:        import java.util.Set;
0029:
0030:        import org.springframework.beans.BeanWrapper;
0031:        import org.springframework.beans.BeansException;
0032:        import org.springframework.beans.PropertyEditorRegistrar;
0033:        import org.springframework.beans.PropertyEditorRegistry;
0034:        import org.springframework.beans.PropertyEditorRegistrySupport;
0035:        import org.springframework.beans.SimpleTypeConverter;
0036:        import org.springframework.beans.TypeConverter;
0037:        import org.springframework.beans.factory.BeanCreationException;
0038:        import org.springframework.beans.factory.BeanCurrentlyInCreationException;
0039:        import org.springframework.beans.factory.BeanDefinitionStoreException;
0040:        import org.springframework.beans.factory.BeanFactory;
0041:        import org.springframework.beans.factory.BeanFactoryUtils;
0042:        import org.springframework.beans.factory.BeanIsAbstractException;
0043:        import org.springframework.beans.factory.BeanIsNotAFactoryException;
0044:        import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
0045:        import org.springframework.beans.factory.CannotLoadBeanClassException;
0046:        import org.springframework.beans.factory.DisposableBean;
0047:        import org.springframework.beans.factory.FactoryBean;
0048:        import org.springframework.beans.factory.FactoryBeanNotInitializedException;
0049:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
0050:        import org.springframework.beans.factory.ObjectFactory;
0051:        import org.springframework.beans.factory.SmartFactoryBean;
0052:        import org.springframework.beans.factory.config.BeanDefinition;
0053:        import org.springframework.beans.factory.config.BeanPostProcessor;
0054:        import org.springframework.beans.factory.config.ConfigurableBeanFactory;
0055:        import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
0056:        import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
0057:        import org.springframework.beans.factory.config.Scope;
0058:        import org.springframework.core.CollectionFactory;
0059:        import org.springframework.util.Assert;
0060:        import org.springframework.util.ClassUtils;
0061:        import org.springframework.util.StringUtils;
0062:
0063:        /**
0064:         * Abstract base class for {@link org.springframework.beans.factory.BeanFactory}
0065:         * implementations, providing the full capabilities of the
0066:         * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI.
0067:         * Does <i>not</i> assume a listable bean factory: can therefore also be used
0068:         * as base class for bean factory implementations which obtain bean definitions
0069:         * from some backend resource (where bean definition access is an expensive operation).
0070:         *
0071:         * <p>This class provides a singleton cache (through its base class
0072:         * {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry},
0073:         * singleton/prototype determination, {@link org.springframework.beans.factory.FactoryBean}
0074:         * handling, aliases, bean definition merging for child bean definitions,
0075:         * and bean destruction ({@link org.springframework.beans.factory.DisposableBean}
0076:         * interface, custom destroy methods). Furthermore, it can manage a bean factory
0077:         * hierarchy (delegating to the parent in case of an unknown bean), through implementing
0078:         * the {@link org.springframework.beans.factory.HierarchicalBeanFactory} interface.
0079:         *
0080:         * <p>The main template methods to be implemented by subclasses are
0081:         * {@link #getBeanDefinition} and {@link #createBean}, retrieving a bean definition
0082:         * for a given bean name and creating a bean instance for a given bean definition,
0083:         * respectively. Default implementations of those operations can be found in
0084:         * {@link DefaultListableBeanFactory} and {@link AbstractAutowireCapableBeanFactory}.
0085:         *
0086:         * @author Rod Johnson
0087:         * @author Juergen Hoeller
0088:         * @since 15 April 2001
0089:         * @see #getBeanDefinition
0090:         * @see #createBean
0091:         * @see AbstractAutowireCapableBeanFactory#createBean
0092:         * @see DefaultListableBeanFactory#getBeanDefinition
0093:         */
0094:        public abstract class AbstractBeanFactory extends
0095:                DefaultSingletonBeanRegistry implements  ConfigurableBeanFactory {
0096:
0097:            /** Parent bean factory, for bean inheritance support */
0098:            private BeanFactory parentBeanFactory;
0099:
0100:            /** ClassLoader to resolve bean class names with, if necessary */
0101:            private ClassLoader beanClassLoader = ClassUtils
0102:                    .getDefaultClassLoader();
0103:
0104:            /** Whether to cache bean metadata or rather reobtain it for every access */
0105:            private boolean cacheBeanMetadata = true;
0106:
0107:            /** Custom PropertyEditors to apply to the beans of this factory */
0108:            private final Map customEditors = new HashMap();
0109:
0110:            /** Custom PropertyEditorRegistrars to apply to the beans of this factory */
0111:            private final Set propertyEditorRegistrars = CollectionFactory
0112:                    .createLinkedSetIfPossible(16);
0113:
0114:            /** BeanPostProcessors to apply in createBean */
0115:            private final List beanPostProcessors = new ArrayList();
0116:
0117:            /** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
0118:            private boolean hasInstantiationAwareBeanPostProcessors;
0119:
0120:            /** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
0121:            private boolean hasDestructionAwareBeanPostProcessors;
0122:
0123:            /** Map from scope identifier String to corresponding Scope */
0124:            private final Map scopes = new HashMap();
0125:
0126:            /** Map from alias to canonical bean name */
0127:            private final Map aliasMap = CollectionFactory
0128:                    .createConcurrentMapIfPossible(16);
0129:
0130:            /** Map from bean name to merged RootBeanDefinition */
0131:            private final Map mergedBeanDefinitions = CollectionFactory
0132:                    .createConcurrentMapIfPossible(16);
0133:
0134:            /** Names of beans that have already been created at least once */
0135:            private final Set alreadyCreated = Collections
0136:                    .synchronizedSet(new HashSet());
0137:
0138:            /** Names of beans that are currently in creation */
0139:            private final ThreadLocal prototypesCurrentlyInCreation = new ThreadLocal();
0140:
0141:            /** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */
0142:            private final Map factoryBeanObjectCache = new HashMap();
0143:
0144:            /**
0145:             * Create a new AbstractBeanFactory.
0146:             */
0147:            public AbstractBeanFactory() {
0148:            }
0149:
0150:            /**
0151:             * Create a new AbstractBeanFactory with the given parent.
0152:             * @param parentBeanFactory parent bean factory, or <code>null</code> if none
0153:             * @see #getBean
0154:             */
0155:            public AbstractBeanFactory(BeanFactory parentBeanFactory) {
0156:                this .parentBeanFactory = parentBeanFactory;
0157:            }
0158:
0159:            //---------------------------------------------------------------------
0160:            // Implementation of BeanFactory interface
0161:            //---------------------------------------------------------------------
0162:
0163:            public Object getBean(String name) throws BeansException {
0164:                return getBean(name, null, null);
0165:            }
0166:
0167:            public Object getBean(String name, Class requiredType)
0168:                    throws BeansException {
0169:                return getBean(name, requiredType, null);
0170:            }
0171:
0172:            /**
0173:             * Return an instance, which may be shared or independent, of the specified bean.
0174:             * @param name the name of the bean to retrieve
0175:             * @param args arguments to use if creating a prototype using explicit arguments to a
0176:             * static factory method. It is invalid to use a non-null args value in any other case.
0177:             * @return an instance of the bean
0178:             * @throws BeansException if the bean could not be created
0179:             */
0180:            public Object getBean(String name, Object[] args)
0181:                    throws BeansException {
0182:                return getBean(name, null, args);
0183:            }
0184:
0185:            /**
0186:             * Return an instance, which may be shared or independent, of the specified bean.
0187:             * @param name the name of the bean to retrieve
0188:             * @param requiredType the required type of the bean to retrieve
0189:             * @param args arguments to use if creating a prototype using explicit arguments to a
0190:             * static factory method. It is invalid to use a non-null args value in any other case.
0191:             * @return an instance of the bean
0192:             * @throws BeansException if the bean could not be created
0193:             */
0194:            public Object getBean(String name, Class requiredType,
0195:                    final Object[] args) throws BeansException {
0196:                final String beanName = transformedBeanName(name);
0197:                Object bean = null;
0198:
0199:                // Eagerly check singleton cache for manually registered singletons.
0200:                Object sharedInstance = getSingleton(beanName);
0201:                if (sharedInstance != null) {
0202:                    if (isSingletonCurrentlyInCreation(beanName)) {
0203:                        if (logger.isDebugEnabled()) {
0204:                            logger
0205:                                    .debug("Returning eagerly cached instance of singleton bean '"
0206:                                            + beanName
0207:                                            + "' that is not fully initialized yet - a consequence of a circular reference");
0208:                        }
0209:                    } else {
0210:                        if (logger.isDebugEnabled()) {
0211:                            logger
0212:                                    .debug("Returning cached instance of singleton bean '"
0213:                                            + beanName + "'");
0214:                        }
0215:                    }
0216:                    if (containsBeanDefinition(beanName)) {
0217:                        RootBeanDefinition mbd = getMergedBeanDefinition(
0218:                                beanName, false);
0219:                        bean = getObjectForBeanInstance(sharedInstance, name,
0220:                                mbd);
0221:                    } else {
0222:                        bean = getObjectForBeanInstance(sharedInstance, name,
0223:                                null);
0224:                    }
0225:                }
0226:
0227:                else {
0228:                    // Fail if we're already creating this bean instance:
0229:                    // We're assumably within a circular reference.
0230:                    if (isPrototypeCurrentlyInCreation(beanName)) {
0231:                        throw new BeanCurrentlyInCreationException(beanName);
0232:                    }
0233:
0234:                    // Check if bean definition exists in this factory.
0235:                    BeanFactory parentBeanFactory = getParentBeanFactory();
0236:                    if (parentBeanFactory != null
0237:                            && !containsBeanDefinition(beanName)) {
0238:                        // Not found -> check parent.
0239:                        String nameToLookup = originalBeanName(name);
0240:                        if (parentBeanFactory instanceof  AbstractBeanFactory) {
0241:                            // Delegation to parent with args only possible for AbstractBeanFactory.
0242:                            return ((AbstractBeanFactory) parentBeanFactory)
0243:                                    .getBean(nameToLookup, requiredType, args);
0244:                        } else if (args == null) {
0245:                            // No args -> delegate to standard getBean method.
0246:                            return parentBeanFactory.getBean(nameToLookup,
0247:                                    requiredType);
0248:                        } else {
0249:                            throw new NoSuchBeanDefinitionException(
0250:                                    beanName,
0251:                                    "Cannot delegate to parent BeanFactory because it does not supported passed-in arguments");
0252:                        }
0253:                    }
0254:
0255:                    this .alreadyCreated.add(beanName);
0256:
0257:                    final RootBeanDefinition mbd = getMergedBeanDefinition(
0258:                            beanName, false);
0259:                    checkMergedBeanDefinition(mbd, beanName, args);
0260:
0261:                    // Create bean instance.
0262:                    if (mbd.isSingleton()) {
0263:                        sharedInstance = getSingleton(beanName,
0264:                                new ObjectFactory() {
0265:                                    public Object getObject()
0266:                                            throws BeansException {
0267:                                        try {
0268:                                            return createBean(beanName, mbd,
0269:                                                    args);
0270:                                        } catch (BeansException ex) {
0271:                                            // Explicitly remove instance from singleton cache: It might have been put there
0272:                                            // eagerly by the creation process, to allow for circular reference resolution.
0273:                                            // Also remove any beans that received a temporary reference to the bean.
0274:                                            destroySingleton(beanName);
0275:                                            throw ex;
0276:                                        }
0277:                                    }
0278:                                });
0279:                        bean = getObjectForBeanInstance(sharedInstance, name,
0280:                                mbd);
0281:                    }
0282:
0283:                    else if (mbd.isPrototype()) {
0284:                        // It's a prototype -> create a new instance.
0285:                        Object prototypeInstance = null;
0286:                        try {
0287:                            beforePrototypeCreation(beanName);
0288:                            prototypeInstance = createBean(beanName, mbd, args);
0289:                        } finally {
0290:                            afterPrototypeCreation(beanName);
0291:                        }
0292:                        bean = getObjectForBeanInstance(prototypeInstance,
0293:                                name, mbd);
0294:                    }
0295:
0296:                    else {
0297:                        String scopeName = mbd.getScope();
0298:                        final Scope scope = (Scope) this .scopes.get(scopeName);
0299:                        if (scope == null) {
0300:                            throw new IllegalStateException(
0301:                                    "No Scope registered for scope '"
0302:                                            + scopeName + "'");
0303:                        }
0304:                        try {
0305:                            Object scopedInstance = scope.get(beanName,
0306:                                    new ObjectFactory() {
0307:                                        public Object getObject()
0308:                                                throws BeansException {
0309:                                            beforePrototypeCreation(beanName);
0310:                                            try {
0311:                                                Object bean = createBean(
0312:                                                        beanName, mbd, args);
0313:                                                if (requiresDestruction(bean,
0314:                                                        mbd)) {
0315:                                                    scope
0316:                                                            .registerDestructionCallback(
0317:                                                                    beanName,
0318:                                                                    new DisposableBeanAdapter(
0319:                                                                            bean,
0320:                                                                            beanName,
0321:                                                                            mbd,
0322:                                                                            getBeanPostProcessors()));
0323:                                                }
0324:                                                return bean;
0325:                                            } finally {
0326:                                                afterPrototypeCreation(beanName);
0327:                                            }
0328:                                        }
0329:                                    });
0330:                            bean = getObjectForBeanInstance(scopedInstance,
0331:                                    name, mbd);
0332:                        } catch (IllegalStateException ex) {
0333:                            throw new BeanCreationException(
0334:                                    beanName,
0335:                                    "Scope '"
0336:                                            + scopeName
0337:                                            + "' is not active for the current thread; "
0338:                                            + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
0339:                                    ex);
0340:                        }
0341:                    }
0342:                }
0343:
0344:                // Check if required type matches the type of the actual bean instance.
0345:                if (requiredType != null
0346:                        && !requiredType.isAssignableFrom(bean.getClass())) {
0347:                    throw new BeanNotOfRequiredTypeException(name,
0348:                            requiredType, bean.getClass());
0349:                }
0350:                return bean;
0351:            }
0352:
0353:            public boolean containsBean(String name) {
0354:                String beanName = transformedBeanName(name);
0355:                if (containsSingleton(beanName)
0356:                        || containsBeanDefinition(beanName)) {
0357:                    return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
0358:                }
0359:                // Not found -> check parent.
0360:                BeanFactory parentBeanFactory = getParentBeanFactory();
0361:                return (parentBeanFactory != null && parentBeanFactory
0362:                        .containsBean(originalBeanName(name)));
0363:            }
0364:
0365:            public boolean isSingleton(String name)
0366:                    throws NoSuchBeanDefinitionException {
0367:                String beanName = transformedBeanName(name);
0368:
0369:                Object beanInstance = getSingleton(beanName);
0370:                if (beanInstance != null) {
0371:                    if (beanInstance instanceof  FactoryBean) {
0372:                        return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean) beanInstance)
0373:                                .isSingleton());
0374:                    } else {
0375:                        return !BeanFactoryUtils.isFactoryDereference(name);
0376:                    }
0377:                }
0378:
0379:                else {
0380:                    // No singleton instance found -> check bean definition.
0381:                    BeanFactory parentBeanFactory = getParentBeanFactory();
0382:                    if (parentBeanFactory != null
0383:                            && !containsBeanDefinition(beanName)) {
0384:                        // No bean definition found in this factory -> delegate to parent.
0385:                        return parentBeanFactory
0386:                                .isSingleton(originalBeanName(name));
0387:                    }
0388:
0389:                    RootBeanDefinition bd = getMergedBeanDefinition(beanName,
0390:                            false);
0391:
0392:                    // In case of FactoryBean, return singleton status of created object if not a dereference.
0393:                    if (bd.isSingleton()) {
0394:                        if (isBeanClassMatch(beanName, bd, FactoryBean.class)) {
0395:                            if (BeanFactoryUtils.isFactoryDereference(name)) {
0396:                                return true;
0397:                            }
0398:                            FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX
0399:                                    + beanName);
0400:                            return factoryBean.isSingleton();
0401:                        } else {
0402:                            return !BeanFactoryUtils.isFactoryDereference(name);
0403:                        }
0404:                    } else {
0405:                        return false;
0406:                    }
0407:                }
0408:            }
0409:
0410:            public boolean isPrototype(String name)
0411:                    throws NoSuchBeanDefinitionException {
0412:                String beanName = transformedBeanName(name);
0413:
0414:                BeanFactory parentBeanFactory = getParentBeanFactory();
0415:                if (parentBeanFactory != null
0416:                        && !containsBeanDefinition(beanName)) {
0417:                    // No bean definition found in this factory -> delegate to parent.
0418:                    return parentBeanFactory
0419:                            .isPrototype(originalBeanName(name));
0420:                }
0421:
0422:                RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
0423:
0424:                // In case of FactoryBean, return singleton status of created object if not a dereference.
0425:                if (bd.isPrototype()) {
0426:                    return (!BeanFactoryUtils.isFactoryDereference(name) || isBeanClassMatch(
0427:                            beanName, bd, FactoryBean.class));
0428:                } else {
0429:                    // Singleton or scoped - not a prototype.
0430:                    // However, FactoryBean may still produce a prototype object...
0431:                    if (!BeanFactoryUtils.isFactoryDereference(name)
0432:                            && isBeanClassMatch(beanName, bd, FactoryBean.class)) {
0433:                        FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX
0434:                                + beanName);
0435:                        return ((factoryBean instanceof  SmartFactoryBean && ((SmartFactoryBean) factoryBean)
0436:                                .isPrototype()) || !factoryBean.isSingleton());
0437:                    } else {
0438:                        return false;
0439:                    }
0440:                }
0441:            }
0442:
0443:            public boolean isTypeMatch(String name, Class targetType)
0444:                    throws NoSuchBeanDefinitionException {
0445:                String beanName = transformedBeanName(name);
0446:                Class typeToMatch = (targetType != null ? targetType
0447:                        : Object.class);
0448:
0449:                // Check manually registered singletons.
0450:                Object beanInstance = getSingleton(beanName);
0451:                if (beanInstance != null) {
0452:                    if (beanInstance instanceof  FactoryBean) {
0453:                        if (!BeanFactoryUtils.isFactoryDereference(name)) {
0454:                            Class type = getTypeForFactoryBean((FactoryBean) beanInstance);
0455:                            return (type != null && typeToMatch
0456:                                    .isAssignableFrom(type));
0457:                        } else {
0458:                            return typeToMatch.isAssignableFrom(beanInstance
0459:                                    .getClass());
0460:                        }
0461:                    } else {
0462:                        return !BeanFactoryUtils.isFactoryDereference(name)
0463:                                && typeToMatch.isAssignableFrom(beanInstance
0464:                                        .getClass());
0465:                    }
0466:                }
0467:
0468:                else {
0469:                    // No singleton instance found -> check bean definition.
0470:                    BeanFactory parentBeanFactory = getParentBeanFactory();
0471:                    if (parentBeanFactory != null
0472:                            && !containsBeanDefinition(beanName)) {
0473:                        // No bean definition found in this factory -> delegate to parent.
0474:                        return parentBeanFactory.isTypeMatch(
0475:                                originalBeanName(name), targetType);
0476:                    }
0477:
0478:                    RootBeanDefinition mbd = getMergedBeanDefinition(beanName,
0479:                            false);
0480:                    Class beanClass = predictBeanType(beanName, mbd);
0481:
0482:                    if (beanClass == null) {
0483:                        return false;
0484:                    }
0485:
0486:                    // Check bean class whether we're dealing with a FactoryBean.
0487:                    if (FactoryBean.class.isAssignableFrom(beanClass)) {
0488:                        if (!BeanFactoryUtils.isFactoryDereference(name)) {
0489:                            // If it's a FactoryBean, we want to look at what it creates, not the factory class.
0490:                            Class type = getTypeForFactoryBean(beanName, mbd);
0491:                            return (type != null && typeToMatch
0492:                                    .isAssignableFrom(type));
0493:                        } else {
0494:                            return typeToMatch.isAssignableFrom(beanClass);
0495:                        }
0496:                    } else {
0497:                        return !BeanFactoryUtils.isFactoryDereference(name)
0498:                                && typeToMatch.isAssignableFrom(beanClass);
0499:                    }
0500:                }
0501:            }
0502:
0503:            public Class getType(String name)
0504:                    throws NoSuchBeanDefinitionException {
0505:                String beanName = transformedBeanName(name);
0506:
0507:                // Check manually registered singletons.
0508:                Object beanInstance = getSingleton(beanName);
0509:                if (beanInstance != null) {
0510:                    if (beanInstance instanceof  FactoryBean
0511:                            && !BeanFactoryUtils.isFactoryDereference(name)) {
0512:                        return getTypeForFactoryBean((FactoryBean) beanInstance);
0513:                    } else {
0514:                        return beanInstance.getClass();
0515:                    }
0516:                }
0517:
0518:                else {
0519:                    // No singleton instance found -> check bean definition.
0520:                    BeanFactory parentBeanFactory = getParentBeanFactory();
0521:                    if (parentBeanFactory != null
0522:                            && !containsBeanDefinition(beanName)) {
0523:                        // No bean definition found in this factory -> delegate to parent.
0524:                        return parentBeanFactory
0525:                                .getType(originalBeanName(name));
0526:                    }
0527:
0528:                    RootBeanDefinition mbd = getMergedBeanDefinition(beanName,
0529:                            false);
0530:                    Class beanClass = predictBeanType(beanName, mbd);
0531:
0532:                    // Check bean class whether we're dealing with a FactoryBean.
0533:                    if (beanClass != null
0534:                            && FactoryBean.class.isAssignableFrom(beanClass)) {
0535:                        if (!BeanFactoryUtils.isFactoryDereference(name)) {
0536:                            // If it's a FactoryBean, we want to look at what it creates, not the factory class.
0537:                            return getTypeForFactoryBean(beanName, mbd);
0538:                        } else {
0539:                            return beanClass;
0540:                        }
0541:                    } else {
0542:                        return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass
0543:                                : null);
0544:                    }
0545:                }
0546:            }
0547:
0548:            public String[] getAliases(String name) {
0549:                String beanName = transformedBeanName(name);
0550:                List aliases = new ArrayList();
0551:                boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
0552:                String fullBeanName = beanName;
0553:                if (factoryPrefix) {
0554:                    fullBeanName = FACTORY_BEAN_PREFIX + beanName;
0555:                }
0556:                if (!fullBeanName.equals(name)) {
0557:                    aliases.add(fullBeanName);
0558:                }
0559:                synchronized (this .aliasMap) {
0560:                    for (Iterator it = this .aliasMap.entrySet().iterator(); it
0561:                            .hasNext();) {
0562:                        Map.Entry entry = (Map.Entry) it.next();
0563:                        if (entry.getValue().equals(beanName)) {
0564:                            String key = (factoryPrefix ? FACTORY_BEAN_PREFIX
0565:                                    : "")
0566:                                    + entry.getKey();
0567:                            if (!key.equals(name)) {
0568:                                aliases.add(key);
0569:                            }
0570:                        }
0571:                    }
0572:                }
0573:                if (!containsSingleton(beanName)
0574:                        && !containsBeanDefinition(beanName)) {
0575:                    BeanFactory parentBeanFactory = getParentBeanFactory();
0576:                    if (parentBeanFactory != null) {
0577:                        aliases.addAll(Arrays.asList(parentBeanFactory
0578:                                .getAliases(fullBeanName)));
0579:                    }
0580:                }
0581:                return StringUtils.toStringArray(aliases);
0582:            }
0583:
0584:            //---------------------------------------------------------------------
0585:            // Implementation of HierarchicalBeanFactory interface
0586:            //---------------------------------------------------------------------
0587:
0588:            public BeanFactory getParentBeanFactory() {
0589:                return this .parentBeanFactory;
0590:            }
0591:
0592:            public boolean containsLocalBean(String name) {
0593:                String beanName = transformedBeanName(name);
0594:                return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) && (!BeanFactoryUtils
0595:                        .isFactoryDereference(name) || isFactoryBean(beanName)));
0596:            }
0597:
0598:            //---------------------------------------------------------------------
0599:            // Implementation of ConfigurableBeanFactory interface
0600:            //---------------------------------------------------------------------
0601:
0602:            public void setParentBeanFactory(BeanFactory parentBeanFactory) {
0603:                if (this .parentBeanFactory != null
0604:                        && this .parentBeanFactory != parentBeanFactory) {
0605:                    throw new IllegalStateException(
0606:                            "Already associated with parent BeanFactory: "
0607:                                    + this .parentBeanFactory);
0608:                }
0609:                this .parentBeanFactory = parentBeanFactory;
0610:            }
0611:
0612:            public void setBeanClassLoader(ClassLoader beanClassLoader) {
0613:                this .beanClassLoader = (beanClassLoader != null ? beanClassLoader
0614:                        : ClassUtils.getDefaultClassLoader());
0615:            }
0616:
0617:            public ClassLoader getBeanClassLoader() {
0618:                return this .beanClassLoader;
0619:            }
0620:
0621:            public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
0622:                this .cacheBeanMetadata = cacheBeanMetadata;
0623:            }
0624:
0625:            public boolean isCacheBeanMetadata() {
0626:                return this .cacheBeanMetadata;
0627:            }
0628:
0629:            public void addPropertyEditorRegistrar(
0630:                    PropertyEditorRegistrar registrar) {
0631:                Assert.notNull(registrar,
0632:                        "PropertyEditorRegistrar must not be null");
0633:                this .propertyEditorRegistrars.add(registrar);
0634:            }
0635:
0636:            /**
0637:             * Return the set of PropertyEditorRegistrars.
0638:             */
0639:            public Set getPropertyEditorRegistrars() {
0640:                return this .propertyEditorRegistrars;
0641:            }
0642:
0643:            public void registerCustomEditor(Class requiredType,
0644:                    PropertyEditor propertyEditor) {
0645:                Assert.notNull(requiredType, "Required type must not be null");
0646:                Assert.notNull(propertyEditor,
0647:                        "PropertyEditor must not be null");
0648:                this .customEditors.put(requiredType, propertyEditor);
0649:            }
0650:
0651:            /**
0652:             * Return the map of custom editors, with Classes as keys
0653:             * and PropertyEditors as values.
0654:             */
0655:            public Map getCustomEditors() {
0656:                return this .customEditors;
0657:            }
0658:
0659:            public TypeConverter getTypeConverter() {
0660:                SimpleTypeConverter typeConverter = new SimpleTypeConverter();
0661:                registerCustomEditors(typeConverter);
0662:                return typeConverter;
0663:            }
0664:
0665:            public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
0666:                Assert.notNull(beanPostProcessor,
0667:                        "BeanPostProcessor must not be null");
0668:                this .beanPostProcessors.add(beanPostProcessor);
0669:                if (beanPostProcessor instanceof  InstantiationAwareBeanPostProcessor) {
0670:                    this .hasInstantiationAwareBeanPostProcessors = true;
0671:                }
0672:                if (beanPostProcessor instanceof  DestructionAwareBeanPostProcessor) {
0673:                    this .hasDestructionAwareBeanPostProcessors = true;
0674:                }
0675:            }
0676:
0677:            public int getBeanPostProcessorCount() {
0678:                return this .beanPostProcessors.size();
0679:            }
0680:
0681:            /**
0682:             * Return the list of BeanPostProcessors that will get applied
0683:             * to beans created with this factory.
0684:             */
0685:            public List getBeanPostProcessors() {
0686:                return this .beanPostProcessors;
0687:            }
0688:
0689:            /**
0690:             * Return whether this factory holds a InstantiationAwareBeanPostProcessor
0691:             * that will get applied to singleton beans on shutdown.
0692:             * @see #addBeanPostProcessor
0693:             * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
0694:             */
0695:            protected boolean hasInstantiationAwareBeanPostProcessors() {
0696:                return this .hasInstantiationAwareBeanPostProcessors;
0697:            }
0698:
0699:            /**
0700:             * Return whether this factory holds a DestructionAwareBeanPostProcessor
0701:             * that will get applied to singleton beans on shutdown.
0702:             * @see #addBeanPostProcessor
0703:             * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
0704:             */
0705:            protected boolean hasDestructionAwareBeanPostProcessors() {
0706:                return this .hasDestructionAwareBeanPostProcessors;
0707:            }
0708:
0709:            public void registerScope(String scopeName, Scope scope) {
0710:                Assert.notNull(scopeName, "Scope identifier must not be null");
0711:                Assert.notNull(scope, "Scope must not be null");
0712:                if (SCOPE_SINGLETON.equals(scopeName)
0713:                        || SCOPE_PROTOTYPE.equals(scopeName)) {
0714:                    throw new IllegalArgumentException(
0715:                            "Cannot replace existing scopes 'singleton' and 'prototype'");
0716:                }
0717:                this .scopes.put(scopeName, scope);
0718:            }
0719:
0720:            public String[] getRegisteredScopeNames() {
0721:                return StringUtils.toStringArray(this .scopes.keySet());
0722:            }
0723:
0724:            public Scope getRegisteredScope(String scopeName) {
0725:                Assert.notNull(scopeName, "Scope identifier must not be null");
0726:                return (Scope) this .scopes.get(scopeName);
0727:            }
0728:
0729:            public void copyConfigurationFrom(
0730:                    ConfigurableBeanFactory otherFactory) {
0731:                Assert.notNull(otherFactory, "BeanFactory must not be null");
0732:                setBeanClassLoader(otherFactory.getBeanClassLoader());
0733:                setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
0734:                if (otherFactory instanceof  AbstractBeanFactory) {
0735:                    AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
0736:                    this .customEditors
0737:                            .putAll(otherAbstractFactory.customEditors);
0738:                    this .propertyEditorRegistrars
0739:                            .addAll(otherAbstractFactory.propertyEditorRegistrars);
0740:                    this .beanPostProcessors
0741:                            .addAll(otherAbstractFactory.beanPostProcessors);
0742:                    this .hasInstantiationAwareBeanPostProcessors = this .hasInstantiationAwareBeanPostProcessors
0743:                            || otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
0744:                    this .hasDestructionAwareBeanPostProcessors = this .hasDestructionAwareBeanPostProcessors
0745:                            || otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
0746:                    this .scopes.putAll(otherAbstractFactory.scopes);
0747:                }
0748:            }
0749:
0750:            public void registerAlias(String beanName, String alias)
0751:                    throws BeanDefinitionStoreException {
0752:                Assert.hasText(beanName, "'beanName' must not be empty");
0753:                Assert.hasText(alias, "'alias' must not be empty");
0754:                if (!alias.equals(beanName)) {
0755:                    // Only actually register the alias if it is not equal to the bean name itself.
0756:                    if (logger.isDebugEnabled()) {
0757:                        logger.debug("Registering alias '" + alias
0758:                                + "' for bean with name '" + beanName + "'");
0759:                    }
0760:                    synchronized (this .aliasMap) {
0761:                        Object registeredName = this .aliasMap.get(alias);
0762:                        if (registeredName != null
0763:                                && !registeredName.equals(beanName)) {
0764:                            throw new BeanDefinitionStoreException(
0765:                                    "Cannot register alias '"
0766:                                            + alias
0767:                                            + "' for bean name '"
0768:                                            + beanName
0769:                                            + "': It's already registered for bean name '"
0770:                                            + registeredName + "'.");
0771:                        }
0772:                        this .aliasMap.put(alias, beanName);
0773:                    }
0774:                }
0775:            }
0776:
0777:            /**
0778:             * Callback before prototype creation.
0779:             * <p>The default implementation register the prototype as currently in creation.
0780:             * @param beanName the name of the prototype about to be created
0781:             * @see #isPrototypeCurrentlyInCreation
0782:             */
0783:            protected void beforePrototypeCreation(String beanName) {
0784:                Object curVal = this .prototypesCurrentlyInCreation.get();
0785:                if (curVal == null) {
0786:                    this .prototypesCurrentlyInCreation.set(beanName);
0787:                } else if (curVal instanceof  String) {
0788:                    Set beanNameSet = new HashSet(2);
0789:                    beanNameSet.add(curVal);
0790:                    beanNameSet.add(beanName);
0791:                    this .prototypesCurrentlyInCreation.set(beanNameSet);
0792:                } else {
0793:                    Set beanNameSet = (Set) curVal;
0794:                    beanNameSet.add(beanName);
0795:                }
0796:            }
0797:
0798:            /**
0799:             * Callback after prototype creation.
0800:             * <p>The default implementation marks the prototype as not in creation anymore.
0801:             * @param beanName the name of the prototype that has been created
0802:             * @see #isPrototypeCurrentlyInCreation
0803:             */
0804:            protected void afterPrototypeCreation(String beanName) {
0805:                Object curVal = this .prototypesCurrentlyInCreation.get();
0806:                if (curVal instanceof  String) {
0807:                    this .prototypesCurrentlyInCreation.set(null);
0808:                } else if (curVal instanceof  Set) {
0809:                    Set beanNameSet = (Set) curVal;
0810:                    beanNameSet.remove(beanName);
0811:                    if (beanNameSet.isEmpty()) {
0812:                        this .prototypesCurrentlyInCreation.set(null);
0813:                    }
0814:                }
0815:            }
0816:
0817:            /**
0818:             * Return whether the specified prototype bean is currently in creation
0819:             * (within the current thread).
0820:             * @param beanName the name of the bean
0821:             */
0822:            protected final boolean isPrototypeCurrentlyInCreation(
0823:                    String beanName) {
0824:                Object curVal = this .prototypesCurrentlyInCreation.get();
0825:                return (curVal != null && (curVal.equals(beanName) || (curVal instanceof  Set && ((Set) curVal)
0826:                        .contains(beanName))));
0827:            }
0828:
0829:            public boolean isCurrentlyInCreation(String beanName) {
0830:                return isSingletonCurrentlyInCreation(beanName)
0831:                        || isPrototypeCurrentlyInCreation(beanName);
0832:            }
0833:
0834:            public void destroyBean(String beanName, Object beanInstance) {
0835:                destroyBean(beanName, beanInstance,
0836:                        getMergedBeanDefinition(beanName));
0837:            }
0838:
0839:            /**
0840:             * Destroy the given bean instance (usually a prototype instance
0841:             * obtained from this factory) according to the given bean definition.
0842:             * @param beanName the name of the bean definition
0843:             * @param beanInstance the bean instance to destroy
0844:             * @param mbd the merged bean definition
0845:             */
0846:            protected void destroyBean(String beanName, Object beanInstance,
0847:                    RootBeanDefinition mbd) {
0848:                new DisposableBeanAdapter(beanInstance, beanName, mbd,
0849:                        getBeanPostProcessors()).destroy();
0850:            }
0851:
0852:            public void destroyScopedBean(String beanName) {
0853:                RootBeanDefinition mbd = getMergedBeanDefinition(beanName);
0854:                if (mbd.isSingleton() || mbd.isPrototype()) {
0855:                    throw new IllegalArgumentException("Bean name '" + beanName
0856:                            + "' does not correspond to an object in a Scope");
0857:                }
0858:                String scopeName = mbd.getScope();
0859:                Scope scope = (Scope) this .scopes.get(scopeName);
0860:                if (scope == null) {
0861:                    throw new IllegalStateException(
0862:                            "No Scope registered for scope '" + scopeName + "'");
0863:                }
0864:                Object bean = scope.remove(beanName);
0865:                if (bean != null) {
0866:                    destroyBean(beanName, bean, mbd);
0867:                }
0868:            }
0869:
0870:            //---------------------------------------------------------------------
0871:            // Implementation methods
0872:            //---------------------------------------------------------------------
0873:
0874:            /**
0875:             * Return the bean name, stripping out the factory dereference prefix if necessary,
0876:             * and resolving aliases to canonical names.
0877:             * @param name the user-specified name
0878:             * @return the transformed bean name
0879:             */
0880:            protected String transformedBeanName(String name) {
0881:                String canonicalName = BeanFactoryUtils
0882:                        .transformedBeanName(name);
0883:                // Handle aliasing.
0884:                String resolvedName = null;
0885:                do {
0886:                    resolvedName = (String) this .aliasMap.get(canonicalName);
0887:                    if (resolvedName != null) {
0888:                        canonicalName = resolvedName;
0889:                    }
0890:                } while (resolvedName != null);
0891:                return canonicalName;
0892:            }
0893:
0894:            /**
0895:             * Determine the original bean name, resolving locally defined aliases to canonical names.
0896:             * @param name the user-specified name
0897:             * @return the original bean name
0898:             */
0899:            protected String originalBeanName(String name) {
0900:                String beanName = transformedBeanName(name);
0901:                if (name.startsWith(FACTORY_BEAN_PREFIX)) {
0902:                    beanName = FACTORY_BEAN_PREFIX + beanName;
0903:                }
0904:                return beanName;
0905:            }
0906:
0907:            /**
0908:             * Determine whether this given bean name is defines as an alias
0909:             * (as opposed to the name of an actual bean definition).
0910:             * @param beanName the bean name to check
0911:             * @return whether the given name is an alias
0912:             */
0913:            protected boolean isAlias(String beanName) {
0914:                return this .aliasMap.containsKey(beanName);
0915:            }
0916:
0917:            /**
0918:             * Initialize the given BeanWrapper with the custom editors registered
0919:             * with this factory. To be called for BeanWrappers that will create
0920:             * and populate bean instances.
0921:             * <p>The default implementation delegates to <code>registerCustomEditors</code>.
0922:             * Can be overridden in subclasses.
0923:             * @param bw the BeanWrapper to initialize
0924:             * @see #registerCustomEditors
0925:             */
0926:            protected void initBeanWrapper(BeanWrapper bw) {
0927:                registerCustomEditors(bw);
0928:            }
0929:
0930:            /**
0931:             * Initialize the given PropertyEditorRegistry with the custom editors
0932:             * registered with this BeanFactory.
0933:             * <p>To be called for BeanWrappers that will create and populate bean
0934:             * instances, and for SimpleTypeConverter used for constructor argument
0935:             * and factory method type conversion.
0936:             * @param registry the PropertyEditorRegistry to initialize
0937:             */
0938:            protected void registerCustomEditors(PropertyEditorRegistry registry) {
0939:                PropertyEditorRegistrySupport registrySupport = (registry instanceof  PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry
0940:                        : null);
0941:                if (registrySupport != null) {
0942:                    registrySupport.useConfigValueEditors();
0943:                }
0944:                for (Iterator it = this .propertyEditorRegistrars.iterator(); it
0945:                        .hasNext();) {
0946:                    PropertyEditorRegistrar registrar = (PropertyEditorRegistrar) it
0947:                            .next();
0948:                    registrar.registerCustomEditors(registry);
0949:                }
0950:                for (Iterator it = this .customEditors.entrySet().iterator(); it
0951:                        .hasNext();) {
0952:                    Map.Entry entry = (Map.Entry) it.next();
0953:                    Class clazz = (Class) entry.getKey();
0954:                    PropertyEditor editor = (PropertyEditor) entry.getValue();
0955:                    // Register the editor as shared instance, if possible,
0956:                    // to make it clear that it might be used concurrently.
0957:                    if (registrySupport != null) {
0958:                        registrySupport.registerSharedEditor(clazz, editor);
0959:                    } else {
0960:                        registry.registerCustomEditor(clazz, editor);
0961:                    }
0962:                }
0963:            }
0964:
0965:            /**
0966:             * Return a RootBeanDefinition for the given bean name,
0967:             * merging a child bean definition with its parent if necessary.
0968:             * @param beanName the name of the bean to retrieve the merged definition for
0969:             * @return a (potentially merged) RootBeanDefinition for the given bean
0970:             * @throws NoSuchBeanDefinitionException if there is no bean with the given name
0971:             * @throws BeanDefinitionStoreException in case of an invalid bean definition
0972:             */
0973:            public RootBeanDefinition getMergedBeanDefinition(String beanName)
0974:                    throws BeansException {
0975:                return getMergedBeanDefinition(beanName, false);
0976:            }
0977:
0978:            /**
0979:             * Return a RootBeanDefinition, even by traversing parent if the parameter is a
0980:             * child definition. Can ask the parent bean factory if not found in this instance.
0981:             * @param beanName the name of the bean to retrieve the merged definition for
0982:             * @param includingAncestors whether to ask the parent bean factory if not found
0983:             * in this instance
0984:             * @return a (potentially merged) RootBeanDefinition for the given bean
0985:             * @throws NoSuchBeanDefinitionException if there is no bean with the given name
0986:             * @throws BeanDefinitionStoreException in case of an invalid bean definition
0987:             */
0988:            protected RootBeanDefinition getMergedBeanDefinition(
0989:                    String beanName, boolean includingAncestors)
0990:                    throws BeansException {
0991:
0992:                // Efficiently check whether bean definition exists in this factory.
0993:                if (includingAncestors
0994:                        && !containsBeanDefinition(beanName)
0995:                        && getParentBeanFactory() instanceof  AbstractBeanFactory) {
0996:                    return ((AbstractBeanFactory) getParentBeanFactory())
0997:                            .getMergedBeanDefinition(beanName, true);
0998:                }
0999:
1000:                // Resolve merged bean definition locally.
1001:                return getMergedBeanDefinition(beanName,
1002:                        getBeanDefinition(beanName));
1003:            }
1004:
1005:            /**
1006:             * Return a RootBeanDefinition for the given top-level bean, by merging with
1007:             * the parent if the given bean's definition is a child bean definition.
1008:             * @param beanName the name of the bean definition
1009:             * @param bd the original bean definition (Root/ChildBeanDefinition)
1010:             * @return a (potentially merged) RootBeanDefinition for the given bean
1011:             * @throws BeanDefinitionStoreException in case of an invalid bean definition
1012:             */
1013:            protected RootBeanDefinition getMergedBeanDefinition(
1014:                    String beanName, BeanDefinition bd)
1015:                    throws BeanDefinitionStoreException {
1016:
1017:                return getMergedBeanDefinition(beanName, bd, null);
1018:            }
1019:
1020:            /**
1021:             * Return a RootBeanDefinition for the given bean, by merging with the
1022:             * parent if the given bean's definition is a child bean definition.
1023:             * @param beanName the name of the bean definition
1024:             * @param bd the original bean definition (Root/ChildBeanDefinition)
1025:             * @param containingBd the containing bean definition in case of inner bean,
1026:             * or <code>null</code> in case of a top-level bean
1027:             * @return a (potentially merged) RootBeanDefinition for the given bean
1028:             * @throws BeanDefinitionStoreException in case of an invalid bean definition
1029:             */
1030:            protected RootBeanDefinition getMergedBeanDefinition(
1031:                    String beanName, BeanDefinition bd,
1032:                    BeanDefinition containingBd)
1033:                    throws BeanDefinitionStoreException {
1034:
1035:                RootBeanDefinition mbd = null;
1036:                // Quick check on the concurrent map first, with minimal locking.
1037:                if (containingBd == null) {
1038:                    mbd = (RootBeanDefinition) this .mergedBeanDefinitions
1039:                            .get(beanName);
1040:                }
1041:                if (mbd == null) {
1042:
1043:                    synchronized (this .mergedBeanDefinitions) {
1044:                        // Second check with full lock now, to enforce the same merged instance.
1045:                        if (containingBd == null) {
1046:                            mbd = (RootBeanDefinition) this .mergedBeanDefinitions
1047:                                    .get(beanName);
1048:                        }
1049:                        if (mbd == null) {
1050:
1051:                            if (bd instanceof  RootBeanDefinition) {
1052:                                // Use copy of given root bean definition.
1053:                                mbd = new RootBeanDefinition(
1054:                                        (RootBeanDefinition) bd);
1055:                            }
1056:
1057:                            else if (bd instanceof  ChildBeanDefinition) {
1058:                                // Child bean definition: needs to be merged with parent.
1059:                                ChildBeanDefinition cbd = (ChildBeanDefinition) bd;
1060:                                RootBeanDefinition pbd = null;
1061:                                try {
1062:                                    String parentBeanName = transformedBeanName(cbd
1063:                                            .getParentName());
1064:                                    if (!beanName.equals(parentBeanName)) {
1065:                                        pbd = getMergedBeanDefinition(
1066:                                                parentBeanName, true);
1067:                                    } else {
1068:                                        if (getParentBeanFactory() instanceof  AbstractBeanFactory) {
1069:                                            AbstractBeanFactory parentFactory = (AbstractBeanFactory) getParentBeanFactory();
1070:                                            pbd = parentFactory
1071:                                                    .getMergedBeanDefinition(
1072:                                                            parentBeanName,
1073:                                                            true);
1074:                                        } else {
1075:                                            throw new NoSuchBeanDefinitionException(
1076:                                                    cbd.getParentName(),
1077:                                                    "Parent name '"
1078:                                                            + cbd
1079:                                                                    .getParentName()
1080:                                                            + "' is equal to bean name '"
1081:                                                            + beanName
1082:                                                            + "': cannot be resolved without an AbstractBeanFactory parent");
1083:                                        }
1084:                                    }
1085:                                } catch (NoSuchBeanDefinitionException ex) {
1086:                                    throw new BeanDefinitionStoreException(
1087:                                            cbd.getResourceDescription(),
1088:                                            beanName,
1089:                                            "Could not resolve parent bean definition '"
1090:                                                    + cbd.getParentName() + "'",
1091:                                            ex);
1092:                                }
1093:
1094:                                // Deep copy with overridden values.
1095:                                mbd = new RootBeanDefinition(pbd);
1096:                                mbd.overrideFrom(cbd);
1097:                            }
1098:
1099:                            else {
1100:                                throw new BeanDefinitionStoreException(bd
1101:                                        .getResourceDescription(), beanName,
1102:                                        "Definition is neither a RootBeanDefinition nor a ChildBeanDefinition: "
1103:                                                + bd);
1104:                            }
1105:
1106:                            // A bean contained in a non-singleton bean cannot be a singleton itself.
1107:                            // Let's correct this on the fly here, since this might be the result of
1108:                            // parent-child merging for the outer bean, in which case the original inner bean
1109:                            // definition will not have inherited the merged outer bean's singleton status.
1110:                            if (containingBd != null
1111:                                    && !containingBd.isSingleton()
1112:                                    && mbd.isSingleton()) {
1113:                                mbd.setSingleton(false);
1114:                            }
1115:
1116:                            // Only cache the merged bean definition if we're already about to create an
1117:                            // instance of the bean, or at least have already created an instance before.
1118:                            if (containingBd == null && isCacheBeanMetadata()
1119:                                    && this .alreadyCreated.contains(beanName)) {
1120:                                this .mergedBeanDefinitions.put(beanName, mbd);
1121:                            }
1122:                        }
1123:                    }
1124:                }
1125:
1126:                return mbd;
1127:            }
1128:
1129:            /**
1130:             * Check the given merged bean definition,
1131:             * potentially throwing validation exceptions.
1132:             * @param mbd the merged bean definition to check
1133:             * @param beanName the name of the bean
1134:             * @param args the arguments for bean creation, if any
1135:             * @throws BeanDefinitionStoreException in case of validation failure
1136:             */
1137:            protected void checkMergedBeanDefinition(RootBeanDefinition mbd,
1138:                    String beanName, Object[] args)
1139:                    throws BeanDefinitionStoreException {
1140:
1141:                // check if bean definition is not abstract
1142:                if (mbd.isAbstract()) {
1143:                    throw new BeanIsAbstractException(beanName);
1144:                }
1145:
1146:                // Check validity of the usage of the args parameter. This can
1147:                // only be used for prototypes constructed via a factory method.
1148:                if (args != null) {
1149:                    if (mbd.isSingleton()) {
1150:                        throw new BeanDefinitionStoreException(
1151:                                "Cannot specify arguments in the getBean() method when referring to a singleton bean definition");
1152:                    } else if (mbd.getFactoryMethodName() == null) {
1153:                        throw new BeanDefinitionStoreException(
1154:                                "Can only specify arguments in the getBean() method in conjunction with a factory method");
1155:                    }
1156:                }
1157:            }
1158:
1159:            /**
1160:             * Remove the merged bean definition for the specified bean,
1161:             * recreating it on next access.
1162:             * @param beanName the bean name to clear the merged definition for
1163:             */
1164:            protected void clearMergedBeanDefinition(String beanName) {
1165:                this .mergedBeanDefinitions.remove(beanName);
1166:            }
1167:
1168:            /**
1169:             * Resolve the bean class for the specified bean definition,
1170:             * resolving a bean class name into a Class reference (if necessary)
1171:             * and storing the resolved Class in the bean definition for further use.
1172:             * @param mbd the merged bean definition to determine the class for
1173:             * @param beanName the name of the bean (for error handling purposes)
1174:             * @return the resolved bean class (or <code>null</code> if none)
1175:             * @throws CannotLoadBeanClassException if we failed to load the class
1176:             */
1177:            protected Class resolveBeanClass(RootBeanDefinition mbd,
1178:                    String beanName) throws CannotLoadBeanClassException {
1179:                if (mbd.hasBeanClass()) {
1180:                    return mbd.getBeanClass();
1181:                }
1182:                try {
1183:                    return mbd.resolveBeanClass(getBeanClassLoader());
1184:                } catch (ClassNotFoundException ex) {
1185:                    throw new CannotLoadBeanClassException(mbd
1186:                            .getResourceDescription(), beanName, mbd
1187:                            .getBeanClassName(), ex);
1188:                } catch (LinkageError err) {
1189:                    throw new CannotLoadBeanClassException(mbd
1190:                            .getResourceDescription(), beanName, mbd
1191:                            .getBeanClassName(), err);
1192:                }
1193:            }
1194:
1195:            /**
1196:             * Check whether the bean class of the given bean definition matches
1197:             * the specified target type. Allows for lazy loading of the actual
1198:             * bean class, provided that the type match can be determined otherwise.
1199:             * <p>The default implementation simply delegates to the standard
1200:             * <code>resolveBeanClass</code> method. Subclasses may override this
1201:             * to use a different strategy, such as a throwaway class loaer.
1202:             * @param beanName the name of the bean (for error handling purposes)
1203:             * @param mbd the merged bean definition to determine the class for
1204:             * @param targetType the type to match against (never <code>null</code>)
1205:             * @return the resolved bean class (or <code>null</code> if none)
1206:             * @throws CannotLoadBeanClassException if we failed to load the class
1207:             * @see #resolveBeanClass
1208:             */
1209:            protected boolean isBeanClassMatch(String beanName,
1210:                    RootBeanDefinition mbd, Class targetType)
1211:                    throws CannotLoadBeanClassException {
1212:
1213:                Class beanClass = resolveBeanClass(mbd, beanName);
1214:                return (beanClass != null && targetType
1215:                        .isAssignableFrom(beanClass));
1216:            }
1217:
1218:            /**
1219:             * Predict the eventual bean type (of the processed bean instance) for the
1220:             * specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
1221:             * Does not need to handle FactoryBeans specifically, since it is only
1222:             * supposed to operate on the raw bean type.
1223:             * <p>This implementation is simplistic in that it is not able to
1224:             * handle factory methods and InstantiationAwareBeanPostProcessors.
1225:             * It only predicts the bean type correctly for a standard bean.
1226:             * To be overridden in subclasses, applying more sophisticated type detection.
1227:             * @param beanName the name of the bean
1228:             * @param mbd the merged bean definition to determine the type for
1229:             * @return the type of the bean, or <code>null</code> if not predictable
1230:             */
1231:            protected Class predictBeanType(String beanName,
1232:                    RootBeanDefinition mbd) {
1233:                if (mbd.getFactoryMethodName() != null) {
1234:                    return null;
1235:                }
1236:                return resolveBeanClass(mbd, beanName);
1237:            }
1238:
1239:            /**
1240:             * Determine the bean type for the given FactoryBean definition, as far as possible.
1241:             * Only called if there is no singleton instance registered for the target bean already.
1242:             * <p>The default implementation creates the FactoryBean via <code>getBean</code>
1243:             * to call its <code>getObjectType</code> method. Subclasses are encouraged to optimize
1244:             * this, typically by just instantiating the FactoryBean but not populating it yet,
1245:             * trying whether its <code>getObjectType</code> method already returns a type.
1246:             * If no type found, a full FactoryBean creation as performed by this implementation
1247:             * should be used as fallback.
1248:             * @param beanName the name of the bean
1249:             * @param mbd the merged bean definition for the bean
1250:             * @return the type for the bean if determinable, or <code>null</code> else
1251:             * @see org.springframework.beans.factory.FactoryBean#getObjectType()
1252:             * @see #getBean(String)
1253:             */
1254:            protected Class getTypeForFactoryBean(String beanName,
1255:                    RootBeanDefinition mbd) {
1256:                if (!mbd.isSingleton()) {
1257:                    return null;
1258:                }
1259:                try {
1260:                    FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX
1261:                            + beanName);
1262:                    return getTypeForFactoryBean(factoryBean);
1263:                } catch (BeanCreationException ex) {
1264:                    // Can only happen when getting a FactoryBean.
1265:                    logger
1266:                            .debug(
1267:                                    "Ignoring bean creation exception on FactoryBean type check",
1268:                                    ex);
1269:                    return null;
1270:                }
1271:            }
1272:
1273:            /**
1274:             * Determine the type for the given FactoryBean.
1275:             * @param factoryBean the FactoryBean instance to check
1276:             * @return the FactoryBean's object type,
1277:             * or <code>null</code> if the type cannot be determined yet
1278:             */
1279:            protected Class getTypeForFactoryBean(FactoryBean factoryBean) {
1280:                try {
1281:                    return factoryBean.getObjectType();
1282:                } catch (Throwable ex) {
1283:                    // Thrown from the FactoryBean's getObjectType implementation.
1284:                    logger
1285:                            .warn(
1286:                                    "FactoryBean threw exception from getObjectType, despite the contract saying "
1287:                                            + "that it should return null if the type of its object cannot be determined yet",
1288:                                    ex);
1289:                    return null;
1290:                }
1291:            }
1292:
1293:            /**
1294:             * Get the object for the given bean instance, either the bean
1295:             * instance itself or its created object in case of a FactoryBean.
1296:             * @param beanInstance the shared bean instance
1297:             * @param name name that may include factory dereference prefix
1298:             * @param mbd the merged bean definition
1299:             * @return the object to expose for the bean
1300:             */
1301:            protected Object getObjectForBeanInstance(Object beanInstance,
1302:                    String name, RootBeanDefinition mbd) {
1303:                // Don't let calling code try to dereference the
1304:                // bean factory if the bean isn't a factory.
1305:                if (BeanFactoryUtils.isFactoryDereference(name)
1306:                        && !(beanInstance instanceof  FactoryBean)) {
1307:                    throw new BeanIsNotAFactoryException(
1308:                            transformedBeanName(name), beanInstance.getClass());
1309:                }
1310:
1311:                boolean shared = (mbd == null || mbd.isSingleton());
1312:                Object object = beanInstance;
1313:
1314:                // Now we have the bean instance, which may be a normal bean or a FactoryBean.
1315:                // If it's a FactoryBean, we use it to create a bean instance, unless the
1316:                // caller actually wants a reference to the factory.
1317:                if (beanInstance instanceof  FactoryBean) {
1318:                    if (!BeanFactoryUtils.isFactoryDereference(name)) {
1319:                        // Return bean instance from factory.
1320:                        FactoryBean factory = (FactoryBean) beanInstance;
1321:                        String beanName = transformedBeanName(name);
1322:                        // Cache object obtained from FactoryBean if it is a singleton.
1323:                        if (shared && factory.isSingleton()) {
1324:                            synchronized (getSingletonMutex()) {
1325:                                object = this .factoryBeanObjectCache
1326:                                        .get(beanName);
1327:                                if (object == null) {
1328:                                    object = getObjectFromFactoryBean(factory,
1329:                                            beanName, mbd);
1330:                                    this .factoryBeanObjectCache.put(beanName,
1331:                                            object);
1332:                                }
1333:                            }
1334:                        } else {
1335:                            object = getObjectFromFactoryBean(factory,
1336:                                    beanName, mbd);
1337:                        }
1338:                    }
1339:                }
1340:
1341:                return object;
1342:            }
1343:
1344:            /**
1345:             * Obtain an object to expose from the given FactoryBean.
1346:             * @param factory the FactoryBean instance
1347:             * @param beanName the name of the bean
1348:             * @param mbd the merged bean definition
1349:             * @return the object obtained from the FactoryBean
1350:             * @throws BeanCreationException if FactoryBean object creation failed
1351:             * @see org.springframework.beans.factory.FactoryBean#getObject()
1352:             */
1353:            private Object getObjectFromFactoryBean(FactoryBean factory,
1354:                    String beanName, RootBeanDefinition mbd)
1355:                    throws BeanCreationException {
1356:
1357:                Object object;
1358:
1359:                try {
1360:                    object = factory.getObject();
1361:                } catch (FactoryBeanNotInitializedException ex) {
1362:                    throw new BeanCurrentlyInCreationException(beanName, ex
1363:                            .toString());
1364:                } catch (Throwable ex) {
1365:                    throw new BeanCreationException(beanName,
1366:                            "FactoryBean threw exception on object creation",
1367:                            ex);
1368:                }
1369:
1370:                // Do not accept a null value for a FactoryBean that's not fully
1371:                // initialized yet: Many FactoryBeans just return null then.
1372:                if (object == null && isSingletonCurrentlyInCreation(beanName)) {
1373:                    throw new BeanCurrentlyInCreationException(beanName,
1374:                            "FactoryBean which is currently in creation returned null from getObject");
1375:                }
1376:
1377:                if (object != null && (mbd == null || !mbd.isSynthetic())) {
1378:                    try {
1379:                        object = postProcessObjectFromFactoryBean(object,
1380:                                beanName);
1381:                    } catch (Throwable ex) {
1382:                        throw new BeanCreationException(
1383:                                mbd.getResourceDescription(),
1384:                                beanName,
1385:                                "Post-processing of the FactoryBean's object failed",
1386:                                ex);
1387:                    }
1388:                }
1389:
1390:                return object;
1391:            }
1392:
1393:            /**
1394:             * Post-process the given object that has been obtained from the FactoryBean.
1395:             * The resulting object will get exposed for bean references.
1396:             * <p>The default implementation simply returns the given object as-is.
1397:             * Subclasses may override this, for example, to apply post-processors.
1398:             * @param object the object obtained from the FactoryBean.
1399:             * @param beanName the name of the bean
1400:             * @return the object to expose
1401:             * @throws BeansException if any post-processing failed
1402:             */
1403:            protected Object postProcessObjectFromFactoryBean(Object object,
1404:                    String beanName) throws BeansException {
1405:                return object;
1406:            }
1407:
1408:            /**
1409:             * Determine whether the bean with the given name is a FactoryBean.
1410:             * @param name the name of the bean to check
1411:             * @return whether the bean is a FactoryBean
1412:             * (<code>false</code> means the bean exists but is not a FactoryBean)
1413:             * @throws NoSuchBeanDefinitionException if there is no bean with the given name
1414:             */
1415:            public boolean isFactoryBean(String name)
1416:                    throws NoSuchBeanDefinitionException {
1417:                String beanName = transformedBeanName(name);
1418:
1419:                Object beanInstance = getSingleton(beanName);
1420:                if (beanInstance != null) {
1421:                    return (beanInstance instanceof  FactoryBean);
1422:                }
1423:
1424:                // No singleton instance found -> check bean definition.
1425:                if (!containsBeanDefinition(beanName)
1426:                        && getParentBeanFactory() instanceof  AbstractBeanFactory) {
1427:                    // No bean definition found in this factory -> delegate to parent.
1428:                    return ((AbstractBeanFactory) getParentBeanFactory())
1429:                            .isFactoryBean(name);
1430:                }
1431:
1432:                RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
1433:                return isBeanClassMatch(beanName, bd, FactoryBean.class);
1434:            }
1435:
1436:            /**
1437:             * Determine whether the given bean name is already in use within this factory,
1438:             * that is, whether there is a local bean registered under this name or
1439:             * an inner bean created with this name.
1440:             * @param beanName the name to check
1441:             */
1442:            protected boolean isBeanNameInUse(String beanName) {
1443:                return containsLocalBean(beanName)
1444:                        || hasDependentBean(beanName);
1445:            }
1446:
1447:            /**
1448:             * Determine whether the given bean requires destruction on shutdown.
1449:             * <p>The default implementation checks the DisposableBean interface as well as
1450:             * a specified destroy method and registered DestructionAwareBeanPostProcessors.
1451:             * @param bean the bean instance to check
1452:             * @param mbd the corresponding bean definition
1453:             * @see org.springframework.beans.factory.DisposableBean
1454:             * @see AbstractBeanDefinition#getDestroyMethodName()
1455:             * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
1456:             */
1457:            protected boolean requiresDestruction(Object bean,
1458:                    RootBeanDefinition mbd) {
1459:                return (bean instanceof  DisposableBean
1460:                        || mbd.getDestroyMethodName() != null || hasDestructionAwareBeanPostProcessors());
1461:            }
1462:
1463:            /**
1464:             * Add the given bean to the list of disposable beans in this factory,
1465:             * registering its DisposableBean interface and/or the given destroy method
1466:             * to be called on factory shutdown (if applicable). Only applies to singletons.
1467:             * <p>Also registers bean as dependent on other beans, according to the
1468:             * "depends-on" configuration in the bean definition.
1469:             * @param beanName the name of the bean
1470:             * @param bean the bean instance
1471:             * @param mbd the bean definition for the bean
1472:             * @see RootBeanDefinition#isSingleton
1473:             * @see RootBeanDefinition#getDependsOn
1474:             * @see #registerDisposableBean
1475:             * @see #registerDependentBean
1476:             */
1477:            protected void registerDisposableBeanIfNecessary(String beanName,
1478:                    Object bean, RootBeanDefinition mbd) {
1479:                if (mbd.isSingleton() && requiresDestruction(bean, mbd)) {
1480:                    // Register a DisposableBean implementation that performs all destruction
1481:                    // work for the given bean: DestructionAwareBeanPostProcessors,
1482:                    // DisposableBean interface, custom destroy method.
1483:                    registerDisposableBean(beanName, new DisposableBeanAdapter(
1484:                            bean, beanName, mbd, getBeanPostProcessors()));
1485:
1486:                    // Register bean as dependent on other beans, if necessary,
1487:                    // for correct shutdown order.
1488:                    String[] dependsOn = mbd.getDependsOn();
1489:                    if (dependsOn != null) {
1490:                        for (int i = 0; i < dependsOn.length; i++) {
1491:                            registerDependentBean(dependsOn[i], beanName);
1492:                        }
1493:                    }
1494:                }
1495:            }
1496:
1497:            /**
1498:             * Overridden to clear the FactoryBean object cache as well.
1499:             */
1500:            protected void removeSingleton(String beanName) {
1501:                super .removeSingleton(beanName);
1502:                this .factoryBeanObjectCache.remove(beanName);
1503:            }
1504:
1505:            //---------------------------------------------------------------------
1506:            // Abstract methods to be implemented by subclasses
1507:            //---------------------------------------------------------------------
1508:
1509:            /**
1510:             * Check if this bean factory contains a bean definition with the given name.
1511:             * Does not consider any hierarchy this factory may participate in.
1512:             * Invoked by <code>containsBean</code> when no cached singleton instance is found.
1513:             * <p>Depending on the nature of the concrete bean factory implementation,
1514:             * this operation might be expensive (for example, because of directory lookups
1515:             * in external registries). However, for listable bean factories, this usually
1516:             * just amounts to a local hash lookup: The operation is therefore part of the
1517:             * public interface there. The same implementation can serve for both this
1518:             * template method and the public interface method in that case.
1519:             * @param beanName the name of the bean to look for
1520:             * @return if this bean factory contains a bean definition with the given name
1521:             * @see #containsBean
1522:             * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
1523:             */
1524:            protected abstract boolean containsBeanDefinition(String beanName);
1525:
1526:            /**
1527:             * Return the bean definition for the given bean name.
1528:             * Subclasses should normally implement caching, as this method is invoked
1529:             * by this class every time bean definition metadata is needed.
1530:             * <p>Depending on the nature of the concrete bean factory implementation,
1531:             * this operation might be expensive (for example, because of directory lookups
1532:             * in external registries). However, for listable bean factories, this usually
1533:             * just amounts to a local hash lookup: The operation is therefore part of the
1534:             * public interface there. The same implementation can serve for both this
1535:             * template method and the public interface method in that case.
1536:             * @param beanName the name of the bean to find a definition for
1537:             * @return the BeanDefinition for this prototype name (never <code>null</code>)
1538:             * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
1539:             * if the bean definition cannot be resolved
1540:             * @throws BeansException in case of errors
1541:             * @see RootBeanDefinition
1542:             * @see ChildBeanDefinition
1543:             * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
1544:             */
1545:            protected abstract BeanDefinition getBeanDefinition(String beanName)
1546:                    throws BeansException;
1547:
1548:            /**
1549:             * Create a bean instance for the given bean definition.
1550:             * The bean definition will already have been merged with the parent
1551:             * definition in case of a child definition.
1552:             * <p>All the other methods in this class invoke this method, although
1553:             * beans may be cached after being instantiated by this method. All bean
1554:             * instantiation within this class is performed by this method.
1555:             * @param beanName the name of the bean
1556:             * @param mbd the merged bean definition for the bean
1557:             * @param args arguments to use if creating a prototype using explicit arguments to a
1558:             * static factory method. This parameter must be <code>null</code> except in this case.
1559:             * @return a new instance of the bean
1560:             * @throws BeanCreationException if the bean could not be created
1561:             */
1562:            protected abstract Object createBean(String beanName,
1563:                    RootBeanDefinition mbd, Object[] args)
1564:                    throws BeanCreationException;
1565:
1566:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.