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.Constructor;
020import java.util.Arrays;
021import java.util.LinkedHashMap;
022import java.util.LinkedHashSet;
023import java.util.Map;
024import java.util.Set;
025
026import org.springframework.beans.BeanMetadataAttributeAccessor;
027import org.springframework.beans.MutablePropertyValues;
028import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
029import org.springframework.beans.factory.config.BeanDefinition;
030import org.springframework.beans.factory.config.ConstructorArgumentValues;
031import org.springframework.core.io.DescriptiveResource;
032import org.springframework.core.io.Resource;
033import org.springframework.util.Assert;
034import org.springframework.util.ClassUtils;
035import org.springframework.util.ObjectUtils;
036import org.springframework.util.StringUtils;
037
038/**
039 * Base class for concrete, full-fledged {@link BeanDefinition} classes,
040 * factoring out common properties of {@link GenericBeanDefinition},
041 * {@link RootBeanDefinition}, and {@link ChildBeanDefinition}.
042 *
043 * <p>The autowire constants match the ones defined in the
044 * {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
045 * interface.
046 *
047 * @author Rod Johnson
048 * @author Juergen Hoeller
049 * @author Rob Harrop
050 * @author Mark Fisher
051 * @see GenericBeanDefinition
052 * @see RootBeanDefinition
053 * @see ChildBeanDefinition
054 */
055@SuppressWarnings("serial")
056public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
057                implements BeanDefinition, Cloneable {
058
059        /**
060         * Constant for the default scope name: {@code ""}, equivalent to singleton
061         * status unless overridden from a parent bean definition (if applicable).
062         */
063        public static final String SCOPE_DEFAULT = "";
064
065        /**
066         * Constant that indicates no autowiring at all.
067         * @see #setAutowireMode
068         */
069        public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
070
071        /**
072         * Constant that indicates autowiring bean properties by name.
073         * @see #setAutowireMode
074         */
075        public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
076
077        /**
078         * Constant that indicates autowiring bean properties by type.
079         * @see #setAutowireMode
080         */
081        public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
082
083        /**
084         * Constant that indicates autowiring a constructor.
085         * @see #setAutowireMode
086         */
087        public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
088
089        /**
090         * Constant that indicates determining an appropriate autowire strategy
091         * through introspection of the bean class.
092         * @see #setAutowireMode
093         * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
094         * use annotation-based autowiring for clearer demarcation of autowiring needs.
095         */
096        @Deprecated
097        public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
098
099        /**
100         * Constant that indicates no dependency check at all.
101         * @see #setDependencyCheck
102         */
103        public static final int DEPENDENCY_CHECK_NONE = 0;
104
105        /**
106         * Constant that indicates dependency checking for object references.
107         * @see #setDependencyCheck
108         */
109        public static final int DEPENDENCY_CHECK_OBJECTS = 1;
110
111        /**
112         * Constant that indicates dependency checking for "simple" properties.
113         * @see #setDependencyCheck
114         * @see org.springframework.beans.BeanUtils#isSimpleProperty
115         */
116        public static final int DEPENDENCY_CHECK_SIMPLE = 2;
117
118        /**
119         * Constant that indicates dependency checking for all properties
120         * (object references as well as "simple" properties).
121         * @see #setDependencyCheck
122         */
123        public static final int DEPENDENCY_CHECK_ALL = 3;
124
125        /**
126         * Constant that indicates the container should attempt to infer the
127         * {@link #setDestroyMethodName destroy method name} for a bean as opposed to
128         * explicit specification of a method name. The value {@value} is specifically
129         * designed to include characters otherwise illegal in a method name, ensuring
130         * no possibility of collisions with legitimately named methods having the same
131         * name.
132         * <p>Currently, the method names detected during destroy method inference
133         * are "close" and "shutdown", if present on the specific bean class.
134         */
135        public static final String INFER_METHOD = "(inferred)";
136
137
138        private volatile Object beanClass;
139
140        private String scope = SCOPE_DEFAULT;
141
142        private boolean abstractFlag = false;
143
144        private boolean lazyInit = false;
145
146        private int autowireMode = AUTOWIRE_NO;
147
148        private int dependencyCheck = DEPENDENCY_CHECK_NONE;
149
150        private String[] dependsOn;
151
152        private boolean autowireCandidate = true;
153
154        private boolean primary = false;
155
156        private final Map<String, AutowireCandidateQualifier> qualifiers =
157                        new LinkedHashMap<String, AutowireCandidateQualifier>(0);
158
159        private boolean nonPublicAccessAllowed = true;
160
161        private boolean lenientConstructorResolution = true;
162
163        private String factoryBeanName;
164
165        private String factoryMethodName;
166
167        private ConstructorArgumentValues constructorArgumentValues;
168
169        private MutablePropertyValues propertyValues;
170
171        private MethodOverrides methodOverrides = new MethodOverrides();
172
173        private String initMethodName;
174
175        private String destroyMethodName;
176
177        private boolean enforceInitMethod = true;
178
179        private boolean enforceDestroyMethod = true;
180
181        private boolean synthetic = false;
182
183        private int role = BeanDefinition.ROLE_APPLICATION;
184
185        private String description;
186
187        private Resource resource;
188
189
190        /**
191         * Create a new AbstractBeanDefinition with default settings.
192         */
193        protected AbstractBeanDefinition() {
194                this(null, null);
195        }
196
197        /**
198         * Create a new AbstractBeanDefinition with the given
199         * constructor argument values and property values.
200         */
201        protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
202                setConstructorArgumentValues(cargs);
203                setPropertyValues(pvs);
204        }
205
206        /**
207         * Create a new AbstractBeanDefinition as a deep copy of the given
208         * bean definition.
209         * @param original the original bean definition to copy from
210         */
211        protected AbstractBeanDefinition(BeanDefinition original) {
212                setParentName(original.getParentName());
213                setBeanClassName(original.getBeanClassName());
214                setScope(original.getScope());
215                setAbstract(original.isAbstract());
216                setLazyInit(original.isLazyInit());
217                setFactoryBeanName(original.getFactoryBeanName());
218                setFactoryMethodName(original.getFactoryMethodName());
219                setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
220                setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
221                setRole(original.getRole());
222                setSource(original.getSource());
223                copyAttributesFrom(original);
224
225                if (original instanceof AbstractBeanDefinition) {
226                        AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original;
227                        if (originalAbd.hasBeanClass()) {
228                                setBeanClass(originalAbd.getBeanClass());
229                        }
230                        setAutowireMode(originalAbd.getAutowireMode());
231                        setDependencyCheck(originalAbd.getDependencyCheck());
232                        setDependsOn(originalAbd.getDependsOn());
233                        setAutowireCandidate(originalAbd.isAutowireCandidate());
234                        setPrimary(originalAbd.isPrimary());
235                        copyQualifiersFrom(originalAbd);
236                        setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
237                        setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
238                        setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
239                        setInitMethodName(originalAbd.getInitMethodName());
240                        setEnforceInitMethod(originalAbd.isEnforceInitMethod());
241                        setDestroyMethodName(originalAbd.getDestroyMethodName());
242                        setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
243                        setSynthetic(originalAbd.isSynthetic());
244                        setResource(originalAbd.getResource());
245                }
246                else {
247                        setResourceDescription(original.getResourceDescription());
248                }
249        }
250
251
252        /**
253         * Override settings in this bean definition (presumably a copied parent
254         * from a parent-child inheritance relationship) from the given bean
255         * definition (presumably the child).
256         * <ul>
257         * <li>Will override beanClass if specified in the given bean definition.
258         * <li>Will always take {@code abstract}, {@code scope},
259         * {@code lazyInit}, {@code autowireMode}, {@code dependencyCheck},
260         * and {@code dependsOn} from the given bean definition.
261         * <li>Will add {@code constructorArgumentValues}, {@code propertyValues},
262         * {@code methodOverrides} from the given bean definition to existing ones.
263         * <li>Will override {@code factoryBeanName}, {@code factoryMethodName},
264         * {@code initMethodName}, and {@code destroyMethodName} if specified
265         * in the given bean definition.
266         * </ul>
267         */
268        public void overrideFrom(BeanDefinition other) {
269                if (StringUtils.hasLength(other.getBeanClassName())) {
270                        setBeanClassName(other.getBeanClassName());
271                }
272                if (StringUtils.hasLength(other.getScope())) {
273                        setScope(other.getScope());
274                }
275                setAbstract(other.isAbstract());
276                setLazyInit(other.isLazyInit());
277                if (StringUtils.hasLength(other.getFactoryBeanName())) {
278                        setFactoryBeanName(other.getFactoryBeanName());
279                }
280                if (StringUtils.hasLength(other.getFactoryMethodName())) {
281                        setFactoryMethodName(other.getFactoryMethodName());
282                }
283                getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
284                getPropertyValues().addPropertyValues(other.getPropertyValues());
285                setRole(other.getRole());
286                setSource(other.getSource());
287                copyAttributesFrom(other);
288
289                if (other instanceof AbstractBeanDefinition) {
290                        AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
291                        if (otherAbd.hasBeanClass()) {
292                                setBeanClass(otherAbd.getBeanClass());
293                        }
294                        setAutowireMode(otherAbd.getAutowireMode());
295                        setDependencyCheck(otherAbd.getDependencyCheck());
296                        setDependsOn(otherAbd.getDependsOn());
297                        setAutowireCandidate(otherAbd.isAutowireCandidate());
298                        setPrimary(otherAbd.isPrimary());
299                        copyQualifiersFrom(otherAbd);
300                        setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
301                        setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
302                        getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
303                        if (StringUtils.hasLength(otherAbd.getInitMethodName())) {
304                                setInitMethodName(otherAbd.getInitMethodName());
305                                setEnforceInitMethod(otherAbd.isEnforceInitMethod());
306                        }
307                        if (otherAbd.getDestroyMethodName() != null) {
308                                setDestroyMethodName(otherAbd.getDestroyMethodName());
309                                setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
310                        }
311                        setSynthetic(otherAbd.isSynthetic());
312                        setResource(otherAbd.getResource());
313                }
314                else {
315                        setResourceDescription(other.getResourceDescription());
316                }
317        }
318
319        /**
320         * Apply the provided default values to this bean.
321         * @param defaults the default settings to apply
322         * @since 2.5
323         */
324        public void applyDefaults(BeanDefinitionDefaults defaults) {
325                setLazyInit(defaults.isLazyInit());
326                setAutowireMode(defaults.getAutowireMode());
327                setDependencyCheck(defaults.getDependencyCheck());
328                setInitMethodName(defaults.getInitMethodName());
329                setEnforceInitMethod(false);
330                setDestroyMethodName(defaults.getDestroyMethodName());
331                setEnforceDestroyMethod(false);
332        }
333
334
335        /**
336         * Specify the bean class name of this bean definition.
337         */
338        @Override
339        public void setBeanClassName(String beanClassName) {
340                this.beanClass = beanClassName;
341        }
342
343        /**
344         * Return the current bean class name of this bean definition.
345         */
346        @Override
347        public String getBeanClassName() {
348                Object beanClassObject = this.beanClass;
349                if (beanClassObject instanceof Class) {
350                        return ((Class<?>) beanClassObject).getName();
351                }
352                else {
353                        return (String) beanClassObject;
354                }
355        }
356
357        /**
358         * Specify the class for this bean.
359         */
360        public void setBeanClass(Class<?> beanClass) {
361                this.beanClass = beanClass;
362        }
363
364        /**
365         * Return the class of the wrapped bean (assuming it is resolved already).
366         * @return the bean class (never {@code null})
367         * @throws IllegalStateException if the bean definition does not define a bean class,
368         * or a specified bean class name has not been resolved into an actual Class yet
369         * @see #hasBeanClass()
370         * @see #setBeanClass(Class)
371         * @see #resolveBeanClass(ClassLoader)
372         */
373        public Class<?> getBeanClass() throws IllegalStateException {
374                Object beanClassObject = this.beanClass;
375                if (beanClassObject == null) {
376                        throw new IllegalStateException("No bean class specified on bean definition");
377                }
378                if (!(beanClassObject instanceof Class)) {
379                        throw new IllegalStateException(
380                                        "Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
381                }
382                return (Class<?>) beanClassObject;
383        }
384
385        /**
386         * Return whether this definition specifies a bean class.
387         * @see #getBeanClass()
388         * @see #setBeanClass(Class)
389         * @see #resolveBeanClass(ClassLoader)
390         */
391        public boolean hasBeanClass() {
392                return (this.beanClass instanceof Class);
393        }
394
395        /**
396         * Determine the class of the wrapped bean, resolving it from a
397         * specified class name if necessary. Will also reload a specified
398         * Class from its name when called with the bean class already resolved.
399         * @param classLoader the ClassLoader to use for resolving a (potential) class name
400         * @return the resolved bean class
401         * @throws ClassNotFoundException if the class name could be resolved
402         */
403        public Class<?> resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {
404                String className = getBeanClassName();
405                if (className == null) {
406                        return null;
407                }
408                Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
409                this.beanClass = resolvedClass;
410                return resolvedClass;
411        }
412
413        /**
414         * Set the name of the target scope for the bean.
415         * <p>The default is singleton status, although this is only applied once
416         * a bean definition becomes active in the containing factory. A bean
417         * definition may eventually inherit its scope from a parent bean definition.
418         * For this reason, the default scope name is an empty string (i.e., {@code ""}),
419         * with singleton status being assumed until a resolved scope is set.
420         * @see #SCOPE_SINGLETON
421         * @see #SCOPE_PROTOTYPE
422         */
423        @Override
424        public void setScope(String scope) {
425                this.scope = scope;
426        }
427
428        /**
429         * Return the name of the target scope for the bean.
430         */
431        @Override
432        public String getScope() {
433                return this.scope;
434        }
435
436        /**
437         * Return whether this a <b>Singleton</b>, with a single shared instance
438         * returned from all calls.
439         * @see #SCOPE_SINGLETON
440         */
441        @Override
442        public boolean isSingleton() {
443                return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);
444        }
445
446        /**
447         * Return whether this a <b>Prototype</b>, with an independent instance
448         * returned for each call.
449         * @see #SCOPE_PROTOTYPE
450         */
451        @Override
452        public boolean isPrototype() {
453                return SCOPE_PROTOTYPE.equals(this.scope);
454        }
455
456        /**
457         * Set if this bean is "abstract", i.e. not meant to be instantiated itself but
458         * rather just serving as parent for concrete child bean definitions.
459         * <p>Default is "false". Specify true to tell the bean factory to not try to
460         * instantiate that particular bean in any case.
461         */
462        public void setAbstract(boolean abstractFlag) {
463                this.abstractFlag = abstractFlag;
464        }
465
466        /**
467         * Return whether this bean is "abstract", i.e. not meant to be instantiated
468         * itself but rather just serving as parent for concrete child bean definitions.
469         */
470        @Override
471        public boolean isAbstract() {
472                return this.abstractFlag;
473        }
474
475        /**
476         * Set whether this bean should be lazily initialized.
477         * <p>If {@code false}, the bean will get instantiated on startup by bean
478         * factories that perform eager initialization of singletons.
479         */
480        @Override
481        public void setLazyInit(boolean lazyInit) {
482                this.lazyInit = lazyInit;
483        }
484
485        /**
486         * Return whether this bean should be lazily initialized, i.e. not
487         * eagerly instantiated on startup. Only applicable to a singleton bean.
488         * @return whether to apply lazy-init semantics ({@code false} by default)
489         */
490        @Override
491        public boolean isLazyInit() {
492                return this.lazyInit;
493        }
494
495        /**
496         * Set the autowire mode. This determines whether any automagical detection
497         * and setting of bean references will happen. Default is AUTOWIRE_NO
498         * which means there won't be convention-based autowiring by name or type
499         * (however, there may still be explicit annotation-driven autowiring).
500         * @param autowireMode the autowire mode to set.
501         * Must be one of the constants defined in this class.
502         * @see #AUTOWIRE_NO
503         * @see #AUTOWIRE_BY_NAME
504         * @see #AUTOWIRE_BY_TYPE
505         * @see #AUTOWIRE_CONSTRUCTOR
506         * @see #AUTOWIRE_AUTODETECT
507         */
508        public void setAutowireMode(int autowireMode) {
509                this.autowireMode = autowireMode;
510        }
511
512        /**
513         * Return the autowire mode as specified in the bean definition.
514         */
515        public int getAutowireMode() {
516                return this.autowireMode;
517        }
518
519        /**
520         * Return the resolved autowire code,
521         * (resolving AUTOWIRE_AUTODETECT to AUTOWIRE_CONSTRUCTOR or AUTOWIRE_BY_TYPE).
522         * @see #AUTOWIRE_AUTODETECT
523         * @see #AUTOWIRE_CONSTRUCTOR
524         * @see #AUTOWIRE_BY_TYPE
525         */
526        public int getResolvedAutowireMode() {
527                if (this.autowireMode == AUTOWIRE_AUTODETECT) {
528                        // Work out whether to apply setter autowiring or constructor autowiring.
529                        // If it has a no-arg constructor it's deemed to be setter autowiring,
530                        // otherwise we'll try constructor autowiring.
531                        Constructor<?>[] constructors = getBeanClass().getConstructors();
532                        for (Constructor<?> constructor : constructors) {
533                                if (constructor.getParameterTypes().length == 0) {
534                                        return AUTOWIRE_BY_TYPE;
535                                }
536                        }
537                        return AUTOWIRE_CONSTRUCTOR;
538                }
539                else {
540                        return this.autowireMode;
541                }
542        }
543
544        /**
545         * Set the dependency check code.
546         * @param dependencyCheck the code to set.
547         * Must be one of the four constants defined in this class.
548         * @see #DEPENDENCY_CHECK_NONE
549         * @see #DEPENDENCY_CHECK_OBJECTS
550         * @see #DEPENDENCY_CHECK_SIMPLE
551         * @see #DEPENDENCY_CHECK_ALL
552         */
553        public void setDependencyCheck(int dependencyCheck) {
554                this.dependencyCheck = dependencyCheck;
555        }
556
557        /**
558         * Return the dependency check code.
559         */
560        public int getDependencyCheck() {
561                return this.dependencyCheck;
562        }
563
564        /**
565         * Set the names of the beans that this bean depends on being initialized.
566         * The bean factory will guarantee that these beans get initialized first.
567         * <p>Note that dependencies are normally expressed through bean properties or
568         * constructor arguments. This property should just be necessary for other kinds
569         * of dependencies like statics (*ugh*) or database preparation on startup.
570         */
571        @Override
572        public void setDependsOn(String... dependsOn) {
573                this.dependsOn = dependsOn;
574        }
575
576        /**
577         * Return the bean names that this bean depends on.
578         */
579        @Override
580        public String[] getDependsOn() {
581                return this.dependsOn;
582        }
583
584        /**
585         * Set whether this bean is a candidate for getting autowired into some other bean.
586         * <p>Note that this flag is designed to only affect type-based autowiring.
587         * It does not affect explicit references by name, which will get resolved even
588         * if the specified bean is not marked as an autowire candidate. As a consequence,
589         * autowiring by name will nevertheless inject a bean if the name matches.
590         * @see #AUTOWIRE_BY_TYPE
591         * @see #AUTOWIRE_BY_NAME
592         */
593        @Override
594        public void setAutowireCandidate(boolean autowireCandidate) {
595                this.autowireCandidate = autowireCandidate;
596        }
597
598        /**
599         * Return whether this bean is a candidate for getting autowired into some other bean.
600         */
601        @Override
602        public boolean isAutowireCandidate() {
603                return this.autowireCandidate;
604        }
605
606        /**
607         * Set whether this bean is a primary autowire candidate.
608         * <p>If this value is {@code true} for exactly one bean among multiple
609         * matching candidates, it will serve as a tie-breaker.
610         */
611        @Override
612        public void setPrimary(boolean primary) {
613                this.primary = primary;
614        }
615
616        /**
617         * Return whether this bean is a primary autowire candidate.
618         */
619        @Override
620        public boolean isPrimary() {
621                return this.primary;
622        }
623
624        /**
625         * Register a qualifier to be used for autowire candidate resolution,
626         * keyed by the qualifier's type name.
627         * @see AutowireCandidateQualifier#getTypeName()
628         */
629        public void addQualifier(AutowireCandidateQualifier qualifier) {
630                this.qualifiers.put(qualifier.getTypeName(), qualifier);
631        }
632
633        /**
634         * Return whether this bean has the specified qualifier.
635         */
636        public boolean hasQualifier(String typeName) {
637                return this.qualifiers.containsKey(typeName);
638        }
639
640        /**
641         * Return the qualifier mapped to the provided type name.
642         */
643        public AutowireCandidateQualifier getQualifier(String typeName) {
644                return this.qualifiers.get(typeName);
645        }
646
647        /**
648         * Return all registered qualifiers.
649         * @return the Set of {@link AutowireCandidateQualifier} objects.
650         */
651        public Set<AutowireCandidateQualifier> getQualifiers() {
652                return new LinkedHashSet<AutowireCandidateQualifier>(this.qualifiers.values());
653        }
654
655        /**
656         * Copy the qualifiers from the supplied AbstractBeanDefinition to this bean definition.
657         * @param source the AbstractBeanDefinition to copy from
658         */
659        public void copyQualifiersFrom(AbstractBeanDefinition source) {
660                Assert.notNull(source, "Source must not be null");
661                this.qualifiers.putAll(source.qualifiers);
662        }
663
664        /**
665         * Specify whether to allow access to non-public constructors and methods,
666         * for the case of externalized metadata pointing to those. The default is
667         * {@code true}; switch this to {@code false} for public access only.
668         * <p>This applies to constructor resolution, factory method resolution,
669         * and also init/destroy methods. Bean property accessors have to be public
670         * in any case and are not affected by this setting.
671         * <p>Note that annotation-driven configuration will still access non-public
672         * members as far as they have been annotated. This setting applies to
673         * externalized metadata in this bean definition only.
674         */
675        public void setNonPublicAccessAllowed(boolean nonPublicAccessAllowed) {
676                this.nonPublicAccessAllowed = nonPublicAccessAllowed;
677        }
678
679        /**
680         * Return whether to allow access to non-public constructors and methods.
681         */
682        public boolean isNonPublicAccessAllowed() {
683                return this.nonPublicAccessAllowed;
684        }
685
686        /**
687         * Specify whether to resolve constructors in lenient mode ({@code true},
688         * which is the default) or to switch to strict resolution (throwing an exception
689         * in case of ambiguous constructors that all match when converting the arguments,
690         * whereas lenient mode would use the one with the 'closest' type matches).
691         */
692        public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
693                this.lenientConstructorResolution = lenientConstructorResolution;
694        }
695
696        /**
697         * Return whether to resolve constructors in lenient mode or in strict mode.
698         */
699        public boolean isLenientConstructorResolution() {
700                return this.lenientConstructorResolution;
701        }
702
703        /**
704         * Specify the factory bean to use, if any.
705         * This the name of the bean to call the specified factory method on.
706         * @see #setFactoryMethodName
707         */
708        @Override
709        public void setFactoryBeanName(String factoryBeanName) {
710                this.factoryBeanName = factoryBeanName;
711        }
712
713        /**
714         * Return the factory bean name, if any.
715         */
716        @Override
717        public String getFactoryBeanName() {
718                return this.factoryBeanName;
719        }
720
721        /**
722         * Specify a factory method, if any. This method will be invoked with
723         * constructor arguments, or with no arguments if none are specified.
724         * The method will be invoked on the specified factory bean, if any,
725         * or otherwise as a static method on the local bean class.
726         * @see #setFactoryBeanName
727         * @see #setBeanClassName
728         */
729        @Override
730        public void setFactoryMethodName(String factoryMethodName) {
731                this.factoryMethodName = factoryMethodName;
732        }
733
734        /**
735         * Return a factory method, if any.
736         */
737        @Override
738        public String getFactoryMethodName() {
739                return this.factoryMethodName;
740        }
741
742        /**
743         * Specify constructor argument values for this bean.
744         */
745        public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) {
746                this.constructorArgumentValues =
747                                (constructorArgumentValues != null ? constructorArgumentValues : new ConstructorArgumentValues());
748        }
749
750        /**
751         * Return constructor argument values for this bean (never {@code null}).
752         */
753        @Override
754        public ConstructorArgumentValues getConstructorArgumentValues() {
755                return this.constructorArgumentValues;
756        }
757
758        /**
759         * Return if there are constructor argument values defined for this bean.
760         */
761        public boolean hasConstructorArgumentValues() {
762                return !this.constructorArgumentValues.isEmpty();
763        }
764
765        /**
766         * Specify property values for this bean, if any.
767         */
768        public void setPropertyValues(MutablePropertyValues propertyValues) {
769                this.propertyValues = (propertyValues != null ? propertyValues : new MutablePropertyValues());
770        }
771
772        /**
773         * Return property values for this bean (never {@code null}).
774         */
775        @Override
776        public MutablePropertyValues getPropertyValues() {
777                return this.propertyValues;
778        }
779
780        /**
781         * Specify method overrides for the bean, if any.
782         */
783        public void setMethodOverrides(MethodOverrides methodOverrides) {
784                this.methodOverrides = (methodOverrides != null ? methodOverrides : new MethodOverrides());
785        }
786
787        /**
788         * Return information about methods to be overridden by the IoC
789         * container. This will be empty if there are no method overrides.
790         * <p>Never returns {@code null}.
791         */
792        public MethodOverrides getMethodOverrides() {
793                return this.methodOverrides;
794        }
795
796        /**
797         * Set the name of the initializer method.
798         * <p>The default is {@code null} in which case there is no initializer method.
799         */
800        public void setInitMethodName(String initMethodName) {
801                this.initMethodName = initMethodName;
802        }
803
804        /**
805         * Return the name of the initializer method.
806         */
807        public String getInitMethodName() {
808                return this.initMethodName;
809        }
810
811        /**
812         * Specify whether or not the configured initializer method is the default.
813         * <p>The default value is {@code true} for a locally specified init method
814         * but switched to {@code false} for a shared setting in a defaults section
815         * (e.g. {@code bean init-method} versus {@code beans default-init-method}
816         * level in XML) which might not apply to all contained bean definitions.
817         * @see #setInitMethodName
818         * @see #applyDefaults
819         */
820        public void setEnforceInitMethod(boolean enforceInitMethod) {
821                this.enforceInitMethod = enforceInitMethod;
822        }
823
824        /**
825         * Indicate whether the configured initializer method is the default.
826         * @see #getInitMethodName()
827         */
828        public boolean isEnforceInitMethod() {
829                return this.enforceInitMethod;
830        }
831
832        /**
833         * Set the name of the destroy method.
834         * <p>The default is {@code null} in which case there is no destroy method.
835         */
836        public void setDestroyMethodName(String destroyMethodName) {
837                this.destroyMethodName = destroyMethodName;
838        }
839
840        /**
841         * Return the name of the destroy method.
842         */
843        public String getDestroyMethodName() {
844                return this.destroyMethodName;
845        }
846
847        /**
848         * Specify whether or not the configured destroy method is the default.
849         * <p>The default value is {@code true} for a locally specified destroy method
850         * but switched to {@code false} for a shared setting in a defaults section
851         * (e.g. {@code bean destroy-method} versus {@code beans default-destroy-method}
852         * level in XML) which might not apply to all contained bean definitions.
853         * @see #setDestroyMethodName
854         * @see #applyDefaults
855         */
856        public void setEnforceDestroyMethod(boolean enforceDestroyMethod) {
857                this.enforceDestroyMethod = enforceDestroyMethod;
858        }
859
860        /**
861         * Indicate whether the configured destroy method is the default.
862         * @see #getDestroyMethodName()
863         */
864        public boolean isEnforceDestroyMethod() {
865                return this.enforceDestroyMethod;
866        }
867
868        /**
869         * Set whether this bean definition is 'synthetic', that is, not defined
870         * by the application itself (for example, an infrastructure bean such
871         * as a helper for auto-proxying, created through {@code <aop:config>}).
872         */
873        public void setSynthetic(boolean synthetic) {
874                this.synthetic = synthetic;
875        }
876
877        /**
878         * Return whether this bean definition is 'synthetic', that is,
879         * not defined by the application itself.
880         */
881        public boolean isSynthetic() {
882                return this.synthetic;
883        }
884
885        /**
886         * Set the role hint for this {@code BeanDefinition}.
887         */
888        public void setRole(int role) {
889                this.role = role;
890        }
891
892        /**
893         * Return the role hint for this {@code BeanDefinition}.
894         */
895        @Override
896        public int getRole() {
897                return this.role;
898        }
899
900        /**
901         * Set a human-readable description of this bean definition.
902         */
903        public void setDescription(String description) {
904                this.description = description;
905        }
906
907        /**
908         * Return a human-readable description of this bean definition.
909         */
910        @Override
911        public String getDescription() {
912                return this.description;
913        }
914
915        /**
916         * Set the resource that this bean definition came from
917         * (for the purpose of showing context in case of errors).
918         */
919        public void setResource(Resource resource) {
920                this.resource = resource;
921        }
922
923        /**
924         * Return the resource that this bean definition came from.
925         */
926        public Resource getResource() {
927                return this.resource;
928        }
929
930        /**
931         * Set a description of the resource that this bean definition
932         * came from (for the purpose of showing context in case of errors).
933         */
934        public void setResourceDescription(String resourceDescription) {
935                this.resource = new DescriptiveResource(resourceDescription);
936        }
937
938        /**
939         * Return a description of the resource that this bean definition
940         * came from (for the purpose of showing context in case of errors).
941         */
942        @Override
943        public String getResourceDescription() {
944                return (this.resource != null ? this.resource.getDescription() : null);
945        }
946
947        /**
948         * Set the originating (e.g. decorated) BeanDefinition, if any.
949         */
950        public void setOriginatingBeanDefinition(BeanDefinition originatingBd) {
951                this.resource = new BeanDefinitionResource(originatingBd);
952        }
953
954        /**
955         * Return the originating BeanDefinition, or {@code null} if none.
956         * Allows for retrieving the decorated bean definition, if any.
957         * <p>Note that this method returns the immediate originator. Iterate through the
958         * originator chain to find the original BeanDefinition as defined by the user.
959         */
960        @Override
961        public BeanDefinition getOriginatingBeanDefinition() {
962                return (this.resource instanceof BeanDefinitionResource ?
963                                ((BeanDefinitionResource) this.resource).getBeanDefinition() : null);
964        }
965
966        /**
967         * Validate this bean definition.
968         * @throws BeanDefinitionValidationException in case of validation failure
969         */
970        public void validate() throws BeanDefinitionValidationException {
971                if (!getMethodOverrides().isEmpty() && getFactoryMethodName() != null) {
972                        throw new BeanDefinitionValidationException(
973                                        "Cannot combine static factory method with method overrides: " +
974                                        "the static factory method must create the instance");
975                }
976
977                if (hasBeanClass()) {
978                        prepareMethodOverrides();
979                }
980        }
981
982        /**
983         * Validate and prepare the method overrides defined for this bean.
984         * Checks for existence of a method with the specified name.
985         * @throws BeanDefinitionValidationException in case of validation failure
986         */
987        public void prepareMethodOverrides() throws BeanDefinitionValidationException {
988                // Check that lookup methods exists.
989                MethodOverrides methodOverrides = getMethodOverrides();
990                if (!methodOverrides.isEmpty()) {
991                        Set<MethodOverride> overrides = methodOverrides.getOverrides();
992                        synchronized (overrides) {
993                                for (MethodOverride mo : overrides) {
994                                        prepareMethodOverride(mo);
995                                }
996                        }
997                }
998        }
999
1000        /**
1001         * Validate and prepare the given method override.
1002         * Checks for existence of a method with the specified name,
1003         * marking it as not overloaded if none found.
1004         * @param mo the MethodOverride object to validate
1005         * @throws BeanDefinitionValidationException in case of validation failure
1006         */
1007        protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
1008                int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
1009                if (count == 0) {
1010                        throw new BeanDefinitionValidationException(
1011                                        "Invalid method override: no method with name '" + mo.getMethodName() +
1012                                        "' on class [" + getBeanClassName() + "]");
1013                }
1014                else if (count == 1) {
1015                        // Mark override as not overloaded, to avoid the overhead of arg type checking.
1016                        mo.setOverloaded(false);
1017                }
1018        }
1019
1020
1021        /**
1022         * Public declaration of Object's {@code clone()} method.
1023         * Delegates to {@link #cloneBeanDefinition()}.
1024         * @see Object#clone()
1025         */
1026        @Override
1027        public Object clone() {
1028                return cloneBeanDefinition();
1029        }
1030
1031        /**
1032         * Clone this bean definition.
1033         * To be implemented by concrete subclasses.
1034         * @return the cloned bean definition object
1035         */
1036        public abstract AbstractBeanDefinition cloneBeanDefinition();
1037
1038        @Override
1039        public boolean equals(Object other) {
1040                if (this == other) {
1041                        return true;
1042                }
1043                if (!(other instanceof AbstractBeanDefinition)) {
1044                        return false;
1045                }
1046
1047                AbstractBeanDefinition that = (AbstractBeanDefinition) other;
1048
1049                if (!ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName())) return false;
1050                if (!ObjectUtils.nullSafeEquals(this.scope, that.scope)) return false;
1051                if (this.abstractFlag != that.abstractFlag) return false;
1052                if (this.lazyInit != that.lazyInit) return false;
1053
1054                if (this.autowireMode != that.autowireMode) return false;
1055                if (this.dependencyCheck != that.dependencyCheck) return false;
1056                if (!Arrays.equals(this.dependsOn, that.dependsOn)) return false;
1057                if (this.autowireCandidate != that.autowireCandidate) return false;
1058                if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) return false;
1059                if (this.primary != that.primary) return false;
1060
1061                if (this.nonPublicAccessAllowed != that.nonPublicAccessAllowed) return false;
1062                if (this.lenientConstructorResolution != that.lenientConstructorResolution) return false;
1063                if (!ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues)) return false;
1064                if (!ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues)) return false;
1065                if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false;
1066
1067                if (!ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName)) return false;
1068                if (!ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName)) return false;
1069                if (!ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName)) return false;
1070                if (this.enforceInitMethod != that.enforceInitMethod) return false;
1071                if (!ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName)) return false;
1072                if (this.enforceDestroyMethod != that.enforceDestroyMethod) return false;
1073
1074                if (this.synthetic != that.synthetic) return false;
1075                if (this.role != that.role) return false;
1076
1077                return super.equals(other);
1078        }
1079
1080        @Override
1081        public int hashCode() {
1082                int hashCode = ObjectUtils.nullSafeHashCode(getBeanClassName());
1083                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.scope);
1084                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.constructorArgumentValues);
1085                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.propertyValues);
1086                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryBeanName);
1087                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryMethodName);
1088                hashCode = 29 * hashCode + super.hashCode();
1089                return hashCode;
1090        }
1091
1092        @Override
1093        public String toString() {
1094                StringBuilder sb = new StringBuilder("class [");
1095                sb.append(getBeanClassName()).append("]");
1096                sb.append("; scope=").append(this.scope);
1097                sb.append("; abstract=").append(this.abstractFlag);
1098                sb.append("; lazyInit=").append(this.lazyInit);
1099                sb.append("; autowireMode=").append(this.autowireMode);
1100                sb.append("; dependencyCheck=").append(this.dependencyCheck);
1101                sb.append("; autowireCandidate=").append(this.autowireCandidate);
1102                sb.append("; primary=").append(this.primary);
1103                sb.append("; factoryBeanName=").append(this.factoryBeanName);
1104                sb.append("; factoryMethodName=").append(this.factoryMethodName);
1105                sb.append("; initMethodName=").append(this.initMethodName);
1106                sb.append("; destroyMethodName=").append(this.destroyMethodName);
1107                if (this.resource != null) {
1108                        sb.append("; defined in ").append(this.resource.getDescription());
1109                }
1110                return sb.toString();
1111        }
1112
1113}