001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory.support;
018
019import java.lang.reflect.AnnotatedElement;
020import java.lang.reflect.Constructor;
021import java.lang.reflect.Executable;
022import java.lang.reflect.Member;
023import java.lang.reflect.Method;
024import java.util.HashSet;
025import java.util.Set;
026import java.util.function.Supplier;
027
028import org.springframework.beans.MutablePropertyValues;
029import org.springframework.beans.factory.config.BeanDefinition;
030import org.springframework.beans.factory.config.BeanDefinitionHolder;
031import org.springframework.beans.factory.config.ConstructorArgumentValues;
032import org.springframework.core.ResolvableType;
033import org.springframework.lang.Nullable;
034import org.springframework.util.Assert;
035
036/**
037 * A root bean definition represents the merged bean definition that backs
038 * a specific bean in a Spring BeanFactory at runtime. It might have been created
039 * from multiple original bean definitions that inherit from each other,
040 * typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}.
041 * A root bean definition is essentially the 'unified' bean definition view at runtime.
042 *
043 * <p>Root bean definitions may also be used for registering individual bean definitions
044 * in the configuration phase. However, since Spring 2.5, the preferred way to register
045 * bean definitions programmatically is the {@link GenericBeanDefinition} class.
046 * GenericBeanDefinition has the advantage that it allows to dynamically define
047 * parent dependencies, not 'hard-coding' the role as a root bean definition.
048 *
049 * @author Rod Johnson
050 * @author Juergen Hoeller
051 * @see GenericBeanDefinition
052 * @see ChildBeanDefinition
053 */
054@SuppressWarnings("serial")
055public class RootBeanDefinition extends AbstractBeanDefinition {
056
057        @Nullable
058        private BeanDefinitionHolder decoratedDefinition;
059
060        @Nullable
061        private AnnotatedElement qualifiedElement;
062
063        /** Determines if the definition needs to be re-merged. */
064        volatile boolean stale;
065
066        boolean allowCaching = true;
067
068        boolean isFactoryMethodUnique = false;
069
070        @Nullable
071        volatile ResolvableType targetType;
072
073        /** Package-visible field for caching the determined Class of a given bean definition. */
074        @Nullable
075        volatile Class<?> resolvedTargetType;
076
077        /** Package-visible field for caching if the bean is a factory bean. */
078        @Nullable
079        volatile Boolean isFactoryBean;
080
081        /** Package-visible field for caching the return type of a generically typed factory method. */
082        @Nullable
083        volatile ResolvableType factoryMethodReturnType;
084
085        /** Package-visible field for caching a unique factory method candidate for introspection. */
086        @Nullable
087        volatile Method factoryMethodToIntrospect;
088
089        /** Common lock for the four constructor fields below. */
090        final Object constructorArgumentLock = new Object();
091
092        /** Package-visible field for caching the resolved constructor or factory method. */
093        @Nullable
094        Executable resolvedConstructorOrFactoryMethod;
095
096        /** Package-visible field that marks the constructor arguments as resolved. */
097        boolean constructorArgumentsResolved = false;
098
099        /** Package-visible field for caching fully resolved constructor arguments. */
100        @Nullable
101        Object[] resolvedConstructorArguments;
102
103        /** Package-visible field for caching partly prepared constructor arguments. */
104        @Nullable
105        Object[] preparedConstructorArguments;
106
107        /** Common lock for the two post-processing fields below. */
108        final Object postProcessingLock = new Object();
109
110        /** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied. */
111        boolean postProcessed = false;
112
113        /** Package-visible field that indicates a before-instantiation post-processor having kicked in. */
114        @Nullable
115        volatile Boolean beforeInstantiationResolved;
116
117        @Nullable
118        private Set<Member> externallyManagedConfigMembers;
119
120        @Nullable
121        private Set<String> externallyManagedInitMethods;
122
123        @Nullable
124        private Set<String> externallyManagedDestroyMethods;
125
126
127        /**
128         * Create a new RootBeanDefinition, to be configured through its bean
129         * properties and configuration methods.
130         * @see #setBeanClass
131         * @see #setScope
132         * @see #setConstructorArgumentValues
133         * @see #setPropertyValues
134         */
135        public RootBeanDefinition() {
136                super();
137        }
138
139        /**
140         * Create a new RootBeanDefinition for a singleton.
141         * @param beanClass the class of the bean to instantiate
142         * @see #setBeanClass
143         */
144        public RootBeanDefinition(@Nullable Class<?> beanClass) {
145                super();
146                setBeanClass(beanClass);
147        }
148
149        /**
150         * Create a new RootBeanDefinition for a singleton bean, constructing each instance
151         * through calling the given supplier (possibly a lambda or method reference).
152         * @param beanClass the class of the bean to instantiate
153         * @param instanceSupplier the supplier to construct a bean instance,
154         * as an alternative to a declaratively specified factory method
155         * @since 5.0
156         * @see #setInstanceSupplier
157         */
158        public <T> RootBeanDefinition(@Nullable Class<T> beanClass, @Nullable Supplier<T> instanceSupplier) {
159                super();
160                setBeanClass(beanClass);
161                setInstanceSupplier(instanceSupplier);
162        }
163
164        /**
165         * Create a new RootBeanDefinition for a scoped bean, constructing each instance
166         * through calling the given supplier (possibly a lambda or method reference).
167         * @param beanClass the class of the bean to instantiate
168         * @param scope the name of the corresponding scope
169         * @param instanceSupplier the supplier to construct a bean instance,
170         * as an alternative to a declaratively specified factory method
171         * @since 5.0
172         * @see #setInstanceSupplier
173         */
174        public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {
175                super();
176                setBeanClass(beanClass);
177                setScope(scope);
178                setInstanceSupplier(instanceSupplier);
179        }
180
181        /**
182         * Create a new RootBeanDefinition for a singleton,
183         * using the given autowire mode.
184         * @param beanClass the class of the bean to instantiate
185         * @param autowireMode by name or type, using the constants in this interface
186         * @param dependencyCheck whether to perform a dependency check for objects
187         * (not applicable to autowiring a constructor, thus ignored there)
188         */
189        public RootBeanDefinition(@Nullable Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
190                super();
191                setBeanClass(beanClass);
192                setAutowireMode(autowireMode);
193                if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
194                        setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
195                }
196        }
197
198        /**
199         * Create a new RootBeanDefinition for a singleton,
200         * providing constructor arguments and property values.
201         * @param beanClass the class of the bean to instantiate
202         * @param cargs the constructor argument values to apply
203         * @param pvs the property values to apply
204         */
205        public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs,
206                        @Nullable MutablePropertyValues pvs) {
207
208                super(cargs, pvs);
209                setBeanClass(beanClass);
210        }
211
212        /**
213         * Create a new RootBeanDefinition for a singleton,
214         * providing constructor arguments and property values.
215         * <p>Takes a bean class name to avoid eager loading of the bean class.
216         * @param beanClassName the name of the class to instantiate
217         */
218        public RootBeanDefinition(String beanClassName) {
219                setBeanClassName(beanClassName);
220        }
221
222        /**
223         * Create a new RootBeanDefinition for a singleton,
224         * providing constructor arguments and property values.
225         * <p>Takes a bean class name to avoid eager loading of the bean class.
226         * @param beanClassName the name of the class to instantiate
227         * @param cargs the constructor argument values to apply
228         * @param pvs the property values to apply
229         */
230        public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
231                super(cargs, pvs);
232                setBeanClassName(beanClassName);
233        }
234
235        /**
236         * Create a new RootBeanDefinition as deep copy of the given
237         * bean definition.
238         * @param original the original bean definition to copy from
239         */
240        public RootBeanDefinition(RootBeanDefinition original) {
241                super(original);
242                this.decoratedDefinition = original.decoratedDefinition;
243                this.qualifiedElement = original.qualifiedElement;
244                this.allowCaching = original.allowCaching;
245                this.isFactoryMethodUnique = original.isFactoryMethodUnique;
246                this.targetType = original.targetType;
247                this.factoryMethodToIntrospect = original.factoryMethodToIntrospect;
248        }
249
250        /**
251         * Create a new RootBeanDefinition as deep copy of the given
252         * bean definition.
253         * @param original the original bean definition to copy from
254         */
255        RootBeanDefinition(BeanDefinition original) {
256                super(original);
257        }
258
259
260        @Override
261        public String getParentName() {
262                return null;
263        }
264
265        @Override
266        public void setParentName(@Nullable String parentName) {
267                if (parentName != null) {
268                        throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
269                }
270        }
271
272        /**
273         * Register a target definition that is being decorated by this bean definition.
274         */
275        public void setDecoratedDefinition(@Nullable BeanDefinitionHolder decoratedDefinition) {
276                this.decoratedDefinition = decoratedDefinition;
277        }
278
279        /**
280         * Return the target definition that is being decorated by this bean definition, if any.
281         */
282        @Nullable
283        public BeanDefinitionHolder getDecoratedDefinition() {
284                return this.decoratedDefinition;
285        }
286
287        /**
288         * Specify the {@link AnnotatedElement} defining qualifiers,
289         * to be used instead of the target class or factory method.
290         * @since 4.3.3
291         * @see #setTargetType(ResolvableType)
292         * @see #getResolvedFactoryMethod()
293         */
294        public void setQualifiedElement(@Nullable AnnotatedElement qualifiedElement) {
295                this.qualifiedElement = qualifiedElement;
296        }
297
298        /**
299         * Return the {@link AnnotatedElement} defining qualifiers, if any.
300         * Otherwise, the factory method and target class will be checked.
301         * @since 4.3.3
302         */
303        @Nullable
304        public AnnotatedElement getQualifiedElement() {
305                return this.qualifiedElement;
306        }
307
308        /**
309         * Specify a generics-containing target type of this bean definition, if known in advance.
310         * @since 4.3.3
311         */
312        public void setTargetType(ResolvableType targetType) {
313                this.targetType = targetType;
314        }
315
316        /**
317         * Specify the target type of this bean definition, if known in advance.
318         * @since 3.2.2
319         */
320        public void setTargetType(@Nullable Class<?> targetType) {
321                this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null);
322        }
323
324        /**
325         * Return the target type of this bean definition, if known
326         * (either specified in advance or resolved on first instantiation).
327         * @since 3.2.2
328         */
329        @Nullable
330        public Class<?> getTargetType() {
331                if (this.resolvedTargetType != null) {
332                        return this.resolvedTargetType;
333                }
334                ResolvableType targetType = this.targetType;
335                return (targetType != null ? targetType.resolve() : null);
336        }
337
338        /**
339         * Return a {@link ResolvableType} for this bean definition,
340         * either from runtime-cached type information or from configuration-time
341         * {@link #setTargetType(ResolvableType)} or {@link #setBeanClass(Class)},
342         * also considering resolved factory method definitions.
343         * @since 5.1
344         * @see #setTargetType(ResolvableType)
345         * @see #setBeanClass(Class)
346         * @see #setResolvedFactoryMethod(Method)
347         */
348        @Override
349        public ResolvableType getResolvableType() {
350                ResolvableType targetType = this.targetType;
351                if (targetType != null) {
352                        return targetType;
353                }
354                ResolvableType returnType = this.factoryMethodReturnType;
355                if (returnType != null) {
356                        return returnType;
357                }
358                Method factoryMethod = this.factoryMethodToIntrospect;
359                if (factoryMethod != null) {
360                        return ResolvableType.forMethodReturnType(factoryMethod);
361                }
362                return super.getResolvableType();
363        }
364
365        /**
366         * Determine preferred constructors to use for default construction, if any.
367         * Constructor arguments will be autowired if necessary.
368         * @return one or more preferred constructors, or {@code null} if none
369         * (in which case the regular no-arg default constructor will be called)
370         * @since 5.1
371         */
372        @Nullable
373        public Constructor<?>[] getPreferredConstructors() {
374                return null;
375        }
376
377        /**
378         * Specify a factory method name that refers to a non-overloaded method.
379         */
380        public void setUniqueFactoryMethodName(String name) {
381                Assert.hasText(name, "Factory method name must not be empty");
382                setFactoryMethodName(name);
383                this.isFactoryMethodUnique = true;
384        }
385
386        /**
387         * Specify a factory method name that refers to an overloaded method.
388         * @since 5.2
389         */
390        public void setNonUniqueFactoryMethodName(String name) {
391                Assert.hasText(name, "Factory method name must not be empty");
392                setFactoryMethodName(name);
393                this.isFactoryMethodUnique = false;
394        }
395
396        /**
397         * Check whether the given candidate qualifies as a factory method.
398         */
399        public boolean isFactoryMethod(Method candidate) {
400                return candidate.getName().equals(getFactoryMethodName());
401        }
402
403        /**
404         * Set a resolved Java Method for the factory method on this bean definition.
405         * @param method the resolved factory method, or {@code null} to reset it
406         * @since 5.2
407         */
408        public void setResolvedFactoryMethod(@Nullable Method method) {
409                this.factoryMethodToIntrospect = method;
410        }
411
412        /**
413         * Return the resolved factory method as a Java Method object, if available.
414         * @return the factory method, or {@code null} if not found or not resolved yet
415         */
416        @Nullable
417        public Method getResolvedFactoryMethod() {
418                return this.factoryMethodToIntrospect;
419        }
420
421        public void registerExternallyManagedConfigMember(Member configMember) {
422                synchronized (this.postProcessingLock) {
423                        if (this.externallyManagedConfigMembers == null) {
424                                this.externallyManagedConfigMembers = new HashSet<>(1);
425                        }
426                        this.externallyManagedConfigMembers.add(configMember);
427                }
428        }
429
430        public boolean isExternallyManagedConfigMember(Member configMember) {
431                synchronized (this.postProcessingLock) {
432                        return (this.externallyManagedConfigMembers != null &&
433                                        this.externallyManagedConfigMembers.contains(configMember));
434                }
435        }
436
437        public void registerExternallyManagedInitMethod(String initMethod) {
438                synchronized (this.postProcessingLock) {
439                        if (this.externallyManagedInitMethods == null) {
440                                this.externallyManagedInitMethods = new HashSet<>(1);
441                        }
442                        this.externallyManagedInitMethods.add(initMethod);
443                }
444        }
445
446        public boolean isExternallyManagedInitMethod(String initMethod) {
447                synchronized (this.postProcessingLock) {
448                        return (this.externallyManagedInitMethods != null &&
449                                        this.externallyManagedInitMethods.contains(initMethod));
450                }
451        }
452
453        public void registerExternallyManagedDestroyMethod(String destroyMethod) {
454                synchronized (this.postProcessingLock) {
455                        if (this.externallyManagedDestroyMethods == null) {
456                                this.externallyManagedDestroyMethods = new HashSet<>(1);
457                        }
458                        this.externallyManagedDestroyMethods.add(destroyMethod);
459                }
460        }
461
462        public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
463                synchronized (this.postProcessingLock) {
464                        return (this.externallyManagedDestroyMethods != null &&
465                                        this.externallyManagedDestroyMethods.contains(destroyMethod));
466                }
467        }
468
469
470        @Override
471        public RootBeanDefinition cloneBeanDefinition() {
472                return new RootBeanDefinition(this);
473        }
474
475        @Override
476        public boolean equals(@Nullable Object other) {
477                return (this == other || (other instanceof RootBeanDefinition && super.equals(other)));
478        }
479
480        @Override
481        public String toString() {
482                return "Root bean: " + super.toString();
483        }
484
485}