001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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 * http://www.opensource.org/licenses/ecl2.php
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 */
016package org.kuali.rice.krad.datadictionary;
017
018import java.io.IOException;
019import java.io.NotSerializableException;
020import java.io.ObjectInputStream;
021import java.io.ObjectStreamException;
022import java.io.Serializable;
023import java.lang.annotation.Annotation;
024import java.lang.ref.Reference;
025import java.lang.ref.WeakReference;
026import java.lang.reflect.InvocationHandler;
027import java.lang.reflect.InvocationTargetException;
028import java.lang.reflect.Method;
029import java.lang.reflect.Proxy;
030import java.security.AccessController;
031import java.security.PrivilegedAction;
032import java.util.ArrayList;
033import java.util.Arrays;
034import java.util.Collection;
035import java.util.HashMap;
036import java.util.HashSet;
037import java.util.LinkedHashMap;
038import java.util.LinkedHashSet;
039import java.util.List;
040import java.util.Map;
041import java.util.Set;
042import java.util.concurrent.ConcurrentHashMap;
043
044import javax.inject.Provider;
045
046import org.springframework.beans.BeansException;
047import org.springframework.beans.FatalBeanException;
048import org.springframework.beans.TypeConverter;
049import org.springframework.beans.factory.BeanCreationException;
050import org.springframework.beans.factory.BeanCurrentlyInCreationException;
051import org.springframework.beans.factory.BeanDefinitionStoreException;
052import org.springframework.beans.factory.BeanFactory;
053import org.springframework.beans.factory.BeanFactoryAware;
054import org.springframework.beans.factory.BeanFactoryUtils;
055import org.springframework.beans.factory.CannotLoadBeanClassException;
056import org.springframework.beans.factory.FactoryBean;
057import org.springframework.beans.factory.NoSuchBeanDefinitionException;
058import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
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.ConfigurableBeanFactory;
064import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
065import org.springframework.beans.factory.config.DependencyDescriptor;
066import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
067import org.springframework.beans.factory.support.AbstractBeanDefinition;
068import org.springframework.beans.factory.support.AutowireCandidateResolver;
069import org.springframework.beans.factory.support.BeanDefinitionRegistry;
070import org.springframework.beans.factory.support.BeanDefinitionValidationException;
071import org.springframework.beans.factory.support.RootBeanDefinition;
072import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver;
073import org.springframework.core.annotation.AnnotationUtils;
074import org.springframework.util.Assert;
075import org.springframework.util.ObjectUtils;
076import org.springframework.util.StringUtils;
077
078/**
079 * Default implementation of the
080 * {@link org.springframework.beans.factory.ListableBeanFactory} and
081 * {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
082 * based on bean definition objects.
083 *
084 * <p>Typical usage is registering all bean definitions first (possibly read
085 * from a bean definition file), before accessing beans. Bean definition lookup
086 * is therefore an inexpensive operation in a local bean definition table,
087 * operating on pre-built bean definition metadata objects.
088 *
089 * <p>Can be used as a standalone bean factory, or as a superclass for custom
090 * bean factories. Note that readers for specific bean definition formats are
091 * typically implemented separately rather than as bean factory subclasses:
092 * see for example {@link org.springframework.beans.factory.support.PropertiesBeanDefinitionReader} and
093 * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
094 *
095 * <p>For an alternative implementation of the
096 * {@link org.springframework.beans.factory.ListableBeanFactory} interface,
097 * have a look at {@link org.springframework.beans.factory.support.StaticListableBeanFactory}, which manages existing
098 * bean instances rather than creating new ones based on bean definitions.
099 *
100 * <p>RICE Implementation note: This class, copied from Spring 3.2.3 contains the fix contributed for
101 * performance problem related to large Spring configuration sets.
102 *
103 * @author Rod Johnson
104 * @author Juergen Hoeller
105 * @author Sam Brannen
106 * @author Costin Leau
107 * @author Chris Beams
108 * @author Phillip Webb
109 * @since 16 April 2001
110 * @see org.springframework.beans.factory.support.StaticListableBeanFactory
111 * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
112 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
113 */
114@SuppressWarnings("serial")
115public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
116                implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
117
118        private static Class<?> javaxInjectProviderClass = null;
119
120        static {
121                ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
122                try {
123                        javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
124                }
125                catch (ClassNotFoundException ex) {
126                        // JSR-330 API not available - Provider interface simply not supported then.
127                }
128        }
129
130
131        /** Map from serialized id to factory instance */
132        private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
133                        new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
134
135        /** Optional id for this factory, for serialization purposes */
136        private String serializationId;
137
138        /** Whether to allow re-registration of a different definition with the same name */
139        private boolean allowBeanDefinitionOverriding = true;
140
141        /** Whether to allow eager class loading even for lazy-init beans */
142        private boolean allowEagerClassLoading = true;
143
144        /** Resolver to use for checking if a bean definition is an autowire candidate */
145        private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
146
147        /** Map from dependency type to corresponding autowired value */
148        private final Map<Class<?>, Object> resolvableDependencies = new HashMap<Class<?>, Object>(16);
149
150        /** Map of bean definition objects, keyed by bean name */
151        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
152
153        /** Map of singleton and non-singleton bean names keyed by dependency type */
154        private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
155
156        /** Map of singleton-only bean names keyed by dependency type */
157        private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
158
159        /** List of bean definition names, in registration order */
160        private final List<String> beanDefinitionNames = new ArrayList<String>();
161
162        /** Whether bean definition metadata may be cached for all beans */
163        private boolean configurationFrozen = false;
164
165        /** Cached array of bean definition names in case of frozen configuration */
166        private String[] frozenBeanDefinitionNames;
167
168    // Rice : performance fix for slow loading Spring context
169    private final Map<String,Set<String>> beanDefinitionsByParent = new ConcurrentHashMap<String, Set<String>>();
170    // Rice : END performance fix for slow loading Spring context
171
172        /**
173         * Create a new DefaultListableBeanFactory.
174         */
175        public DefaultListableBeanFactory() {
176                super();
177        }
178
179        /**
180         * Create a new DefaultListableBeanFactory with the given parent.
181         * @param parentBeanFactory the parent BeanFactory
182         */
183        public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
184                super(parentBeanFactory);
185        }
186
187
188        /**
189         * Specify an id for serialization purposes, allowing this BeanFactory to be
190         * deserialized from this id back into the BeanFactory object, if needed.
191         */
192        public void setSerializationId(String serializationId) {
193                if (serializationId != null) {
194                        serializableFactories.put(serializationId, new WeakReference<DefaultListableBeanFactory>(this));
195                }
196                else if (this.serializationId != null) {
197                        serializableFactories.remove(this.serializationId);
198                }
199                this.serializationId = serializationId;
200        }
201
202        /**
203         * Set whether it should be allowed to override bean definitions by registering
204         * a different definition with the same name, automatically replacing the former.
205         * If not, an exception will be thrown. This also applies to overriding aliases.
206         * <p>Default is "true".
207         * @see #registerBeanDefinition
208         */
209        public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
210                this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
211        }
212
213        /**
214         * Set whether the factory is allowed to eagerly load bean classes
215         * even for bean definitions that are marked as "lazy-init".
216         * <p>Default is "true". Turn this flag off to suppress class loading
217         * for lazy-init beans unless such a bean is explicitly requested.
218         * In particular, by-type lookups will then simply ignore bean definitions
219         * without resolved class name, instead of loading the bean classes on
220         * demand just to perform a type check.
221         * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setLazyInit
222         */
223        public void setAllowEagerClassLoading(boolean allowEagerClassLoading) {
224                this.allowEagerClassLoading = allowEagerClassLoading;
225        }
226
227        /**
228         * Set a custom autowire candidate resolver for this BeanFactory to use
229         * when deciding whether a bean definition should be considered as a
230         * candidate for autowiring.
231         */
232        public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
233                Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
234                if (autowireCandidateResolver instanceof BeanFactoryAware) {
235                        if (System.getSecurityManager() != null) {
236                                final BeanFactory target = this;
237                                AccessController.doPrivileged(new PrivilegedAction<Object>() {
238                                        public Object run() {
239                                                ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target);
240                                                return null;
241                                        }
242                                }, getAccessControlContext());
243                        }
244                        else {
245                                ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
246                        }
247                }
248                this.autowireCandidateResolver = autowireCandidateResolver;
249        }
250
251        /**
252         * Return the autowire candidate resolver for this BeanFactory (never {@code null}).
253         */
254        public AutowireCandidateResolver getAutowireCandidateResolver() {
255                return this.autowireCandidateResolver;
256        }
257
258
259        @Override
260        public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
261                super.copyConfigurationFrom(otherFactory);
262                if (otherFactory instanceof DefaultListableBeanFactory) {
263                        DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
264                        this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
265                        this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
266                        this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
267                        this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
268                }
269        }
270
271
272        //---------------------------------------------------------------------
273        // Implementation of ListableBeanFactory interface
274        //---------------------------------------------------------------------
275
276        public <T> T getBean(Class<T> requiredType) throws BeansException {
277                Assert.notNull(requiredType, "Required type must not be null");
278                String[] beanNames = getBeanNamesForType(requiredType);
279                if (beanNames.length > 1) {
280                        ArrayList<String> autowireCandidates = new ArrayList<String>();
281                        for (String beanName : beanNames) {
282                                if (getBeanDefinition(beanName).isAutowireCandidate()) {
283                                        autowireCandidates.add(beanName);
284                                }
285                        }
286                        if (autowireCandidates.size() > 0) {
287                                beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
288                        }
289                }
290                if (beanNames.length == 1) {
291                        return getBean(beanNames[0], requiredType);
292                }
293                else if (beanNames.length > 1) {
294                        T primaryBean = null;
295                        for (String beanName : beanNames) {
296                                T beanInstance = getBean(beanName, requiredType);
297                                if (isPrimary(beanName, beanInstance)) {
298                                        if (primaryBean != null) {
299                                                throw new NoUniqueBeanDefinitionException(requiredType, beanNames.length,
300                                                                "more than one 'primary' bean found of required type: " + Arrays.asList(beanNames));
301                                        }
302                                        primaryBean = beanInstance;
303                                }
304                        }
305                        if (primaryBean != null) {
306                                return primaryBean;
307                        }
308                        throw new NoUniqueBeanDefinitionException(requiredType, beanNames);
309                }
310                else if (getParentBeanFactory() != null) {
311                        return getParentBeanFactory().getBean(requiredType);
312                }
313                else {
314                        throw new NoSuchBeanDefinitionException(requiredType);
315                }
316        }
317
318        @Override
319        public boolean containsBeanDefinition(String beanName) {
320                Assert.notNull(beanName, "Bean name must not be null");
321                return this.beanDefinitionMap.containsKey(beanName);
322        }
323
324        public int getBeanDefinitionCount() {
325                return this.beanDefinitionMap.size();
326        }
327
328        public String[] getBeanDefinitionNames() {
329                synchronized (this.beanDefinitionMap) {
330                        if (this.frozenBeanDefinitionNames != null) {
331                                return this.frozenBeanDefinitionNames;
332                        }
333                        else {
334                                return StringUtils.toStringArray(this.beanDefinitionNames);
335                        }
336                }
337        }
338
339        public String[] getBeanNamesForType(Class<?> type) {
340                return getBeanNamesForType(type, true, true);
341        }
342
343        public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
344                if (!isConfigurationFrozen()  || type == null || !allowEagerInit) {
345                        return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
346                }
347                Map<Class<?>, String[]> cache =
348                                (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
349                String[] resolvedBeanNames = cache.get(type);
350                if (resolvedBeanNames != null) {
351                        return resolvedBeanNames;
352                }
353                resolvedBeanNames = doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
354                cache.put(type, resolvedBeanNames);
355                return resolvedBeanNames;
356        }
357
358        private String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
359                List<String> result = new ArrayList<String>();
360
361                // Check all bean definitions.
362                String[] beanDefinitionNames = getBeanDefinitionNames();
363                for (String beanName : beanDefinitionNames) {
364                        // Only consider bean as eligible if the bean name
365                        // is not defined as alias for some other bean.
366                        if (!isAlias(beanName)) {
367                                try {
368                                        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
369                                        // Only check bean definition if it is complete.
370                                        if (!mbd.isAbstract() && (allowEagerInit ||
371                                                        ((mbd.hasBeanClass() || !mbd.isLazyInit() || this.allowEagerClassLoading)) &&
372                                                                        !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
373                                                // In case of FactoryBean, match object created by FactoryBean.
374                                                boolean isFactoryBean = isFactoryBean(beanName, mbd);
375                                                boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
376                                                                (includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
377                                                if (!matchFound && isFactoryBean) {
378                                                        // In case of FactoryBean, try to match FactoryBean instance itself next.
379                                                        beanName = FACTORY_BEAN_PREFIX + beanName;
380                                                        matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
381                                                }
382                                                if (matchFound) {
383                                                        result.add(beanName);
384                                                }
385                                        }
386                                }
387                                catch (CannotLoadBeanClassException ex) {
388                                        if (allowEagerInit) {
389                                                throw ex;
390                                        }
391                                        // Probably contains a placeholder: let's ignore it for type matching purposes.
392                                        if (this.logger.isDebugEnabled()) {
393                                                this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
394                                        }
395                                        onSuppressedException(ex);
396                                }
397                                catch (BeanDefinitionStoreException ex) {
398                                        if (allowEagerInit) {
399                                                throw ex;
400                                        }
401                                        // Probably contains a placeholder: let's ignore it for type matching purposes.
402                                        if (this.logger.isDebugEnabled()) {
403                                                this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
404                                        }
405                                        onSuppressedException(ex);
406                                }
407                        }
408                }
409
410                // Check singletons too, to catch manually registered singletons.
411                String[] singletonNames = getSingletonNames();
412                for (String beanName : singletonNames) {
413                        // Only check if manually registered.
414                        if (!containsBeanDefinition(beanName)) {
415                                // In case of FactoryBean, match object created by FactoryBean.
416                                if (isFactoryBean(beanName)) {
417                                        if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
418                                                result.add(beanName);
419                                                // Match found for this bean: do not match FactoryBean itself anymore.
420                                                continue;
421                                        }
422                                        // In case of FactoryBean, try to match FactoryBean itself next.
423                                        beanName = FACTORY_BEAN_PREFIX + beanName;
424                                }
425                                // Match raw bean instance (might be raw FactoryBean).
426                                if (isTypeMatch(beanName, type)) {
427                                        result.add(beanName);
428                                }
429                        }
430                }
431
432                return StringUtils.toStringArray(result);
433        }
434
435        /**
436         * Check whether the specified bean would need to be eagerly initialized
437         * in order to determine its type.
438         * @param factoryBeanName a factory-bean reference that the bean definition
439         * defines a factory method for
440         * @return whether eager initialization is necessary
441         */
442        private boolean requiresEagerInitForType(String factoryBeanName) {
443                return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName));
444        }
445
446        public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
447                return getBeansOfType(type, true, true);
448        }
449
450        public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
451                        throws BeansException {
452
453                String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
454                Map<String, T> result = new LinkedHashMap<String, T>(beanNames.length);
455                for (String beanName : beanNames) {
456                        try {
457                                result.put(beanName, getBean(beanName, type));
458                        }
459                        catch (BeanCreationException ex) {
460                                Throwable rootCause = ex.getMostSpecificCause();
461                                if (rootCause instanceof BeanCurrentlyInCreationException) {
462                                        BeanCreationException bce = (BeanCreationException) rootCause;
463                                        if (isCurrentlyInCreation(bce.getBeanName())) {
464                                                if (this.logger.isDebugEnabled()) {
465                                                        this.logger.debug("Ignoring match to currently created bean '" + beanName + "': " +
466                                                                        ex.getMessage());
467                                                }
468                                                onSuppressedException(ex);
469                                                // Ignore: indicates a circular reference when autowiring constructors.
470                                                // We want to find matches other than the currently created bean itself.
471                                                continue;
472                                        }
473                                }
474                                throw ex;
475                        }
476                }
477                return result;
478        }
479
480        public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
481                Set<String> beanNames = new LinkedHashSet<String>(getBeanDefinitionCount());
482                beanNames.addAll(Arrays.asList(getBeanDefinitionNames()));
483                beanNames.addAll(Arrays.asList(getSingletonNames()));
484                Map<String, Object> results = new LinkedHashMap<String, Object>();
485                for (String beanName : beanNames) {
486                        if (findAnnotationOnBean(beanName, annotationType) != null) {
487                                results.put(beanName, getBean(beanName));
488                        }
489                }
490                return results;
491        }
492
493        /**
494         * Find a {@link Annotation} of {@code annotationType} on the specified
495         * bean, traversing its interfaces and super classes if no annotation can be
496         * found on the given class itself, as well as checking its raw bean class
497         * if not found on the exposed bean reference (e.g. in case of a proxy).
498         */
499        public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) {
500                A ann = null;
501                Class<?> beanType = getType(beanName);
502                if (beanType != null) {
503                        ann = AnnotationUtils.findAnnotation(beanType, annotationType);
504                }
505                if (ann == null && containsBeanDefinition(beanName)) {
506                        BeanDefinition bd = getMergedBeanDefinition(beanName);
507                        if (bd instanceof AbstractBeanDefinition) {
508                                AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
509                                if (abd.hasBeanClass()) {
510                                        ann = AnnotationUtils.findAnnotation(abd.getBeanClass(), annotationType);
511                                }
512                        }
513                }
514                return ann;
515        }
516
517
518        //---------------------------------------------------------------------
519        // Implementation of ConfigurableListableBeanFactory interface
520        //---------------------------------------------------------------------
521
522        public void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) {
523                Assert.notNull(dependencyType, "Type must not be null");
524                if (autowiredValue != null) {
525                        Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)),
526                                        "Value [" + autowiredValue + "] does not implement specified type [" + dependencyType.getName() + "]");
527                        this.resolvableDependencies.put(dependencyType, autowiredValue);
528                }
529        }
530
531        public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
532                        throws NoSuchBeanDefinitionException {
533
534                // Consider FactoryBeans as autowiring candidates.
535                boolean isFactoryBean = (descriptor != null && descriptor.getDependencyType() != null &&
536                                FactoryBean.class.isAssignableFrom(descriptor.getDependencyType()));
537                if (isFactoryBean) {
538                        beanName = BeanFactoryUtils.transformedBeanName(beanName);
539                }
540
541                if (containsBeanDefinition(beanName)) {
542                        return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanName), descriptor);
543                }
544                else if (containsSingleton(beanName)) {
545                        return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor);
546                }
547                else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
548                        // No bean definition found in this factory -> delegate to parent.
549                        return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
550                }
551                else {
552                        return true;
553                }
554        }
555
556        /**
557         * Determine whether the specified bean definition qualifies as an autowire candidate,
558         * to be injected into other beans which declare a dependency of matching type.
559         * @param beanName the name of the bean definition to check
560         * @param mbd the merged bean definition to check
561         * @param descriptor the descriptor of the dependency to resolve
562         * @return whether the bean should be considered as autowire candidate
563         */
564        protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) {
565                resolveBeanClass(mbd, beanName);
566
567        // Rice : removing code due to package restrictions, not used in dictionary
568//              if (mbd.isFactoryMethodUnique) {
569//                      boolean resolve;
570//                      synchronized (mbd.constructorArgumentLock) {
571//                              resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
572//                      }
573//                      if (resolve) {
574//                              new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
575//                      }
576//              }
577        // Rice : end code removal
578
579                return getAutowireCandidateResolver().isAutowireCandidate(
580                                new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor);
581        }
582
583        @Override
584        public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
585                BeanDefinition bd = this.beanDefinitionMap.get(beanName);
586                if (bd == null) {
587                        if (this.logger.isTraceEnabled()) {
588                                this.logger.trace("No bean named '" + beanName + "' found in " + this);
589                        }
590                        throw new NoSuchBeanDefinitionException(beanName);
591                }
592                return bd;
593        }
594
595        public void freezeConfiguration() {
596                this.configurationFrozen = true;
597                synchronized (this.beanDefinitionMap) {
598                        this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
599                }
600        }
601
602        public boolean isConfigurationFrozen() {
603                return this.configurationFrozen;
604        }
605
606        /**
607         * Considers all beans as eligible for metadata caching
608         * if the factory's configuration has been marked as frozen.
609         * @see #freezeConfiguration()
610         */
611        @Override
612        protected boolean isBeanEligibleForMetadataCaching(String beanName) {
613                return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
614        }
615
616        public void preInstantiateSingletons() throws BeansException {
617                if (this.logger.isTraceEnabled()) {
618                        this.logger.info("Pre-instantiating singletons in " + this);
619                } else if (this.logger.isInfoEnabled()) {
620            this.logger.info("Pre-instantiating singletons");
621        }
622                List<String> beanNames;
623                synchronized (this.beanDefinitionMap) {
624                        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
625                        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
626                        beanNames = new ArrayList<String>(this.beanDefinitionNames);
627                }
628                for (String beanName : beanNames) {
629                        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
630                        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
631                                if (isFactoryBean(beanName)) {
632                                        final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
633                                        boolean isEagerInit;
634                                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
635                                                isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
636                                                        public Boolean run() {
637                                                                return ((SmartFactoryBean<?>) factory).isEagerInit();
638                                                        }
639                                                }, getAccessControlContext());
640                                        }
641                                        else {
642                                                isEagerInit = (factory instanceof SmartFactoryBean &&
643                                                                ((SmartFactoryBean<?>) factory).isEagerInit());
644                                        }
645                                        if (isEagerInit) {
646                                                getBean(beanName);
647                                        }
648                                }
649                                else {
650                                        getBean(beanName);
651                                }
652                        }
653                }
654        }
655
656
657        //---------------------------------------------------------------------
658        // Implementation of BeanDefinitionRegistry interface
659        //---------------------------------------------------------------------
660
661        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
662                        throws BeanDefinitionStoreException {
663
664                Assert.hasText(beanName, "Bean name must not be empty");
665                Assert.notNull(beanDefinition, "BeanDefinition must not be null");
666
667                if (beanDefinition instanceof AbstractBeanDefinition) {
668                        try {
669                                ((AbstractBeanDefinition) beanDefinition).validate();
670                        }
671                        catch (BeanDefinitionValidationException ex) {
672                                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
673                                                "Validation of bean definition failed", ex);
674                        }
675                }
676
677                synchronized (this.beanDefinitionMap) {
678                        Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
679                        if (oldBeanDefinition != null) {
680                                if (!this.allowBeanDefinitionOverriding) {
681                                        throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
682                                                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
683                                                        "': There is already [" + oldBeanDefinition + "] bound.");
684                                }
685                                else {
686                                        if (this.logger.isInfoEnabled()) {
687                                                this.logger.info("Overriding bean definition for bean '" + beanName +
688                                                                "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
689                                        }
690                                }
691                        }
692                        else {
693                                this.beanDefinitionNames.add(beanName);
694                                this.frozenBeanDefinitionNames = null;
695                        }
696                        this.beanDefinitionMap.put(beanName, beanDefinition);
697                }
698
699                resetBeanDefinition(beanName);
700        }
701
702        public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
703                Assert.hasText(beanName, "'beanName' must not be empty");
704
705                synchronized (this.beanDefinitionMap) {
706                        BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
707                        if (bd == null) {
708                                if (this.logger.isTraceEnabled()) {
709                                        this.logger.trace("No bean named '" + beanName + "' found in " + this);
710                                }
711                                throw new NoSuchBeanDefinitionException(beanName);
712                        }
713                        this.beanDefinitionNames.remove(beanName);
714                        this.frozenBeanDefinitionNames = null;
715            // Rice : performance fix for slow loading Spring context
716            // Pull it out of the parent map
717            if ( StringUtils.hasText( bd.getParentName() ) ) {
718                if ( beanDefinitionsByParent.get(bd.getParentName()) != null ) {
719                    beanDefinitionsByParent.get(bd.getParentName()).remove(beanName);
720                }
721            }
722            // Rice : END performance fix for slow loading Spring context
723                }
724
725                resetBeanDefinition(beanName);
726        }
727
728        /**
729         * Reset all bean definition caches for the given bean,
730         * including the caches of beans that are derived from it.
731         * @param beanName the name of the bean to reset
732         */
733        protected void resetBeanDefinition(String beanName) {
734                // Remove the merged bean definition for the given bean, if already created.
735                clearMergedBeanDefinition(beanName);
736
737                // Remove corresponding bean from singleton cache, if any. Shouldn't usually
738                // be necessary, rather just meant for overriding a context's default beans
739                // (e.g. the default StaticMessageSource in a StaticApplicationContext).
740                destroySingleton(beanName);
741
742                // Remove any assumptions about by-type mappings.
743                clearByTypeCache();
744
745                // Reset all bean definitions that have the given bean as parent (recursively).
746        // Rice : performance fix for slow loading Spring context
747        Set<String> childBeans = beanDefinitionsByParent.get(beanName);
748        if ( childBeans != null ) {
749            for ( String childBeanName : childBeans ) {
750                resetBeanDefinition(childBeanName);
751            }
752        }
753        // Rice: Existing code was O(n!), since the bean definition names list keeps getting longer
754//              for (String bdName : this.beanDefinitionNames) {
755//                      if (!beanName.equals(bdName)) {
756//                              BeanDefinition bd = this.beanDefinitionMap.get(bdName);
757//                              if (beanName.equals(bd.getParentName())) {
758//                                      resetBeanDefinition(bdName);
759//                              }
760//                      }
761//              }
762        // Rice : END performance fix for slow loading Spring context
763        }
764
765    // Rice : performance fix for slow loading Spring context
766    protected void addBeanToParentMap( String parentName, String beanName ) {
767        Set<String> defs = beanDefinitionsByParent.get(parentName);
768        if ( defs == null ) {
769            defs = new HashSet<String>();
770            beanDefinitionsByParent.put(parentName, defs);
771        }
772        defs.add(beanName);
773    }
774    // Rice : END performance fix for slow loading Spring context
775        
776        /**
777         * Only allows alias overriding if bean definition overriding is allowed.
778         */
779        @Override
780        protected boolean allowAliasOverriding() {
781                return this.allowBeanDefinitionOverriding;
782        }
783
784        @Override
785        public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
786                super.registerSingleton(beanName, singletonObject);
787                clearByTypeCache();
788        }
789
790        @Override
791        public void destroySingleton(String beanName) {
792                super.destroySingleton(beanName);
793                clearByTypeCache();
794        }
795
796        /**
797         * Remove any assumptions about by-type mappings.
798         */
799        private void clearByTypeCache() {
800                this.allBeanNamesByType.clear();
801                this.singletonBeanNamesByType.clear();
802        }
803
804
805        //---------------------------------------------------------------------
806        // Dependency resolution functionality
807        //---------------------------------------------------------------------
808
809        public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
810                        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
811
812                descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
813                if (descriptor.getDependencyType().equals(ObjectFactory.class)) {
814                        return new DependencyObjectFactory(descriptor, beanName);
815                }
816                else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) {
817                        return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
818                }
819                else {
820                        return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);
821                }
822        }
823
824        protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,
825                        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
826
827                Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
828                if (value != null) {
829                        if (value instanceof String) {
830                                String strVal = resolveEmbeddedValue((String) value);
831                                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
832                                value = evaluateBeanDefinitionString(strVal, bd);
833                        }
834                        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
835                        return (descriptor.getField() != null ?
836                                        converter.convertIfNecessary(value, type, descriptor.getField()) :
837                                        converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
838                }
839
840                if (type.isArray()) {
841                        Class<?> componentType = type.getComponentType();
842                        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
843                        if (matchingBeans.isEmpty()) {
844                                if (descriptor.isRequired()) {
845                                        raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
846                                }
847                                return null;
848                        }
849                        if (autowiredBeanNames != null) {
850                                autowiredBeanNames.addAll(matchingBeans.keySet());
851                        }
852                        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
853                        return converter.convertIfNecessary(matchingBeans.values(), type);
854                }
855                else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
856                        Class<?> elementType = descriptor.getCollectionType();
857                        if (elementType == null) {
858                                if (descriptor.isRequired()) {
859                                        throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
860                                }
861                                return null;
862                        }
863                        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
864                        if (matchingBeans.isEmpty()) {
865                                if (descriptor.isRequired()) {
866                                        raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
867                                }
868                                return null;
869                        }
870                        if (autowiredBeanNames != null) {
871                                autowiredBeanNames.addAll(matchingBeans.keySet());
872                        }
873                        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
874                        return converter.convertIfNecessary(matchingBeans.values(), type);
875                }
876                else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
877                        Class<?> keyType = descriptor.getMapKeyType();
878                        if (keyType == null || !String.class.isAssignableFrom(keyType)) {
879                                if (descriptor.isRequired()) {
880                                        throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
881                                                        "] must be assignable to [java.lang.String]");
882                                }
883                                return null;
884                        }
885                        Class<?> valueType = descriptor.getMapValueType();
886                        if (valueType == null) {
887                                if (descriptor.isRequired()) {
888                                        throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
889                                }
890                                return null;
891                        }
892                        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
893                        if (matchingBeans.isEmpty()) {
894                                if (descriptor.isRequired()) {
895                                        raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
896                                }
897                                return null;
898                        }
899                        if (autowiredBeanNames != null) {
900                                autowiredBeanNames.addAll(matchingBeans.keySet());
901                        }
902                        return matchingBeans;
903                }
904                else {
905                        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
906                        if (matchingBeans.isEmpty()) {
907                                if (descriptor.isRequired()) {
908                                        raiseNoSuchBeanDefinitionException(type, "", descriptor);
909                                }
910                                return null;
911                        }
912                        if (matchingBeans.size() > 1) {
913                                String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
914                                if (primaryBeanName == null) {
915                                        throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
916                                }
917                                if (autowiredBeanNames != null) {
918                                        autowiredBeanNames.add(primaryBeanName);
919                                }
920                                return matchingBeans.get(primaryBeanName);
921                        }
922                        // We have exactly one match.
923                        Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
924                        if (autowiredBeanNames != null) {
925                                autowiredBeanNames.add(entry.getKey());
926                        }
927                        return entry.getValue();
928                }
929        }
930
931        /**
932         * Find bean instances that match the required type.
933         * Called during autowiring for the specified bean.
934         * @param beanName the name of the bean that is about to be wired
935         * @param requiredType the actual type of bean to look for
936         * (may be an array component type or collection element type)
937         * @param descriptor the descriptor of the dependency to resolve
938         * @return a Map of candidate names and candidate instances that match
939         * the required type (never {@code null})
940         * @throws BeansException in case of errors
941         * @see #autowireByType
942         * @see #autowireConstructor
943         */
944        protected Map<String, Object> findAutowireCandidates(
945                        String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
946
947                String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
948                                this, requiredType, true, descriptor.isEager());
949                Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
950                for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
951                        if (autowiringType.isAssignableFrom(requiredType)) {
952                                Object autowiringValue = this.resolvableDependencies.get(autowiringType);
953                                autowiringValue = resolveAutowiringValue(autowiringValue, requiredType);
954                                if (requiredType.isInstance(autowiringValue)) {
955                                        result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
956                                        break;
957                                }
958                        }
959                }
960                for (String candidateName : candidateNames) {
961                        if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
962                                result.put(candidateName, getBean(candidateName));
963                        }
964                }
965                return result;
966        }
967
968    // Rice : copying code from AutowireUtils due to package restrictions
969    protected static Object resolveAutowiringValue(Object autowiringValue, Class requiredType) {
970                if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) {
971                        ObjectFactory factory = (ObjectFactory) autowiringValue;
972                        if (autowiringValue instanceof Serializable && requiredType.isInterface()) {
973                                autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(), new Class[]{requiredType},
974                           new ObjectFactoryDelegatingInvocationHandler(factory));
975                        }
976                        else {
977                                return factory.getObject();
978                        }
979                }
980                return autowiringValue;
981        }
982
983    /**
984         * Reflective InvocationHandler for lazy access to the current target object.
985         */
986        private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable {
987
988                private final ObjectFactory objectFactory;
989
990                public ObjectFactoryDelegatingInvocationHandler(ObjectFactory objectFactory) {
991                        this.objectFactory = objectFactory;
992                }
993
994                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
995                        String methodName = method.getName();
996                        if (methodName.equals("equals")) {
997                                // Only consider equal when proxies are identical.
998                                return (proxy == args[0]);
999                        }
1000                        else if (methodName.equals("hashCode")) {
1001                                // Use hashCode of proxy.
1002                                return System.identityHashCode(proxy);
1003                        }
1004                        else if (methodName.equals("toString")) {
1005                                return this.objectFactory.toString();
1006                        }
1007                        try {
1008                                return method.invoke(this.objectFactory.getObject(), args);
1009                        }
1010                        catch (InvocationTargetException ex) {
1011                                throw ex.getTargetException();
1012                        }
1013                }
1014        }
1015    // Rice : end code copy
1016
1017        /**
1018         * Determine the primary autowire candidate in the given set of beans.
1019         * @param candidateBeans a Map of candidate names and candidate instances
1020         * that match the required type, as returned by {@link #findAutowireCandidates}
1021         * @param descriptor the target dependency to match against
1022         * @return the name of the primary candidate, or {@code null} if none found
1023         */
1024        protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {
1025                String primaryBeanName = null;
1026                String fallbackBeanName = null;
1027                for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
1028                        String candidateBeanName = entry.getKey();
1029                        Object beanInstance = entry.getValue();
1030                        if (isPrimary(candidateBeanName, beanInstance)) {
1031                                if (primaryBeanName != null) {
1032                                        boolean candidateLocal = containsBeanDefinition(candidateBeanName);
1033                                        boolean primaryLocal = containsBeanDefinition(primaryBeanName);
1034                                        if (candidateLocal == primaryLocal) {
1035                                                throw new NoUniqueBeanDefinitionException(descriptor.getDependencyType(), candidateBeans.size(),
1036                                                                "more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
1037                                        }
1038                                        else if (candidateLocal && !primaryLocal) {
1039                                                primaryBeanName = candidateBeanName;
1040                                        }
1041                                }
1042                                else {
1043                                        primaryBeanName = candidateBeanName;
1044                                }
1045                        }
1046                        if (primaryBeanName == null &&
1047                                        (this.resolvableDependencies.values().contains(beanInstance) ||
1048                                                        matchesBeanName(candidateBeanName, descriptor.getDependencyName()))) {
1049                                fallbackBeanName = candidateBeanName;
1050                        }
1051                }
1052                return (primaryBeanName != null ? primaryBeanName : fallbackBeanName);
1053        }
1054
1055        /**
1056         * Return whether the bean definition for the given bean name has been
1057         * marked as a primary bean.
1058         * @param beanName the name of the bean
1059         * @param beanInstance the corresponding bean instance
1060         * @return whether the given bean qualifies as primary
1061         */
1062        protected boolean isPrimary(String beanName, Object beanInstance) {
1063                if (containsBeanDefinition(beanName)) {
1064                        return getMergedLocalBeanDefinition(beanName).isPrimary();
1065                }
1066                BeanFactory parentFactory = getParentBeanFactory();
1067                return (parentFactory instanceof DefaultListableBeanFactory &&
1068                                ((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
1069        }
1070
1071        /**
1072         * Determine whether the given candidate name matches the bean name or the aliases
1073         * stored in this bean definition.
1074         */
1075        protected boolean matchesBeanName(String beanName, String candidateName) {
1076                return (candidateName != null &&
1077                                (candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
1078        }
1079
1080        /**
1081         * Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
1082         */
1083        private void raiseNoSuchBeanDefinitionException(
1084                        Class<?> type, String dependencyDescription, DependencyDescriptor descriptor)
1085                        throws NoSuchBeanDefinitionException {
1086
1087                throw new NoSuchBeanDefinitionException(type, dependencyDescription,
1088                                "expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
1089                                "Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
1090        }
1091
1092
1093        @Override
1094        public String toString() {
1095                StringBuilder sb = new StringBuilder(ObjectUtils.identityToString(this));
1096                sb.append(": defining beans [");
1097                sb.append(StringUtils.arrayToCommaDelimitedString(getBeanDefinitionNames()));
1098                sb.append("]; ");
1099                BeanFactory parent = getParentBeanFactory();
1100                if (parent == null) {
1101                        sb.append("root of factory hierarchy");
1102                }
1103                else {
1104                        sb.append("parent: ").append(ObjectUtils.identityToString(parent));
1105                }
1106                return sb.toString();
1107        }
1108
1109
1110        //---------------------------------------------------------------------
1111        // Serialization support
1112        //---------------------------------------------------------------------
1113
1114        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1115                throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " +
1116                                "just a SerializedBeanFactoryReference is");
1117        }
1118
1119        protected Object writeReplace() throws ObjectStreamException {
1120                if (this.serializationId != null) {
1121                        return new SerializedBeanFactoryReference(this.serializationId);
1122                }
1123                else {
1124                        throw new NotSerializableException("DefaultListableBeanFactory has no serialization id");
1125                }
1126        }
1127
1128
1129        /**
1130         * Minimal id reference to the factory.
1131         * Resolved to the actual factory instance on deserialization.
1132         */
1133        private static class SerializedBeanFactoryReference implements Serializable {
1134
1135                private final String id;
1136
1137                public SerializedBeanFactoryReference(String id) {
1138                        this.id = id;
1139                }
1140
1141                private Object readResolve() {
1142                        Reference<?> ref = serializableFactories.get(this.id);
1143                        if (ref == null) {
1144                                throw new IllegalStateException(
1145                                                "Cannot deserialize BeanFactory with id " + this.id + ": no factory registered for this id");
1146                        }
1147                        Object result = ref.get();
1148                        if (result == null) {
1149                                throw new IllegalStateException(
1150                                                "Cannot deserialize BeanFactory with id " + this.id + ": factory has been garbage-collected");
1151                        }
1152                        return result;
1153                }
1154        }
1155
1156
1157        /**
1158         * Serializable ObjectFactory for lazy resolution of a dependency.
1159         */
1160        private class DependencyObjectFactory implements ObjectFactory<Object>, Serializable {
1161
1162                private final DependencyDescriptor descriptor;
1163
1164                private final String beanName;
1165
1166                public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) {
1167                        this.descriptor = new DependencyDescriptor(descriptor);
1168                        this.descriptor.increaseNestingLevel();
1169                        this.beanName = beanName;
1170                }
1171
1172                public Object getObject() throws BeansException {
1173                        return doResolveDependency(this.descriptor, this.descriptor.getDependencyType(), this.beanName, null, null);
1174                }
1175        }
1176
1177
1178        /**
1179         * Serializable ObjectFactory for lazy resolution of a dependency.
1180         */
1181        private class DependencyProvider extends DependencyObjectFactory implements Provider<Object> {
1182
1183                public DependencyProvider(DependencyDescriptor descriptor, String beanName) {
1184                        super(descriptor, beanName);
1185                }
1186
1187                public Object get() throws BeansException {
1188                        return getObject();
1189                }
1190        }
1191
1192
1193        /**
1194         * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API.
1195         */
1196        private class DependencyProviderFactory {
1197
1198                public Object createDependencyProvider(DependencyDescriptor descriptor, String beanName) {
1199                        return new DependencyProvider(descriptor, beanName);
1200                }
1201        }
1202
1203}
1204