/* * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.support; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.springframework.beans.BeanMetadataAttributeAccessor; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.core.io.DescriptiveResource; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** * Base class for concrete, full-fledged * {@link org.springframework.beans.factory.config.BeanDefinition} classes, * factoring out common properties of {@link RootBeanDefinition} and * {@link ChildBeanDefinition}. * * <p>The autowire constants match the ones defined in the * {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory} * interface. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop * @author Mark Fisher * @see RootBeanDefinition * @see ChildBeanDefinition */ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { /** * Constant that indicates no autowiring at all. * @see #setAutowireMode */ public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; /** * Constant that indicates autowiring bean properties by name. * @see #setAutowireMode */ public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; /** * Constant that indicates autowiring bean properties by type. * @see #setAutowireMode */ public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; /** * Constant that indicates autowiring a constructor. * @see #setAutowireMode */ public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; /** * Constant that indicates determining an appropriate autowire strategy * through introspection of the bean class. * @see #setAutowireMode */ public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT; /** * Constant that indicates no dependency check at all. * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_NONE = 0; /** * Constant that indicates dependency checking for object references. * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_OBJECTS = 1; /** * Constant that indicates dependency checking for "simple" properties. * @see #setDependencyCheck * @see org.springframework.beans.BeanUtils#isSimpleProperty */ public static final int DEPENDENCY_CHECK_SIMPLE = 2; /** * Constant that indicates dependency checking for all properties * (object references as well as "simple" properties). * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_ALL = 3; private volatile Object beanClass; private String scope = SCOPE_SINGLETON; private boolean singleton = true; private boolean prototype = false; private boolean abstractFlag = false; private boolean lazyInit = false; private int autowireMode = AUTOWIRE_NO; private int dependencyCheck = DEPENDENCY_CHECK_NONE; private String[] dependsOn; private boolean autowireCandidate = true; private final Map qualifiers = new LinkedHashMap(); private boolean primary = false; private ConstructorArgumentValues constructorArgumentValues; private MutablePropertyValues propertyValues; private MethodOverrides methodOverrides = new MethodOverrides(); private String factoryBeanName; private String factoryMethodName; private String initMethodName; private String destroyMethodName; private boolean enforceInitMethod = true; private boolean enforceDestroyMethod = true; private boolean synthetic = false; private int role = BeanDefinition.ROLE_APPLICATION; private String description; private Resource resource; /** * Create a new AbstractBeanDefinition with default settings. */ protected AbstractBeanDefinition() { this(null, null); } /** * Create a new AbstractBeanDefinition with the given * constructor argument values and property values. */ protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) { setConstructorArgumentValues(cargs); setPropertyValues(pvs); } /** * Create a new AbstractBeanDefinition as deep copy of the given * bean definition. * @param original the original bean definition to copy from * @deprecated since Spring 2.5, in favor of {@link #AbstractBeanDefinition(BeanDefinition)} */ protected AbstractBeanDefinition(AbstractBeanDefinition original) { this((BeanDefinition) original); } /** * Create a new AbstractBeanDefinition as deep copy of the given * bean definition. * @param original the original bean definition to copy from */ protected AbstractBeanDefinition(BeanDefinition original) { setParentName(original.getParentName()); setBeanClassName(original.getBeanClassName()); setFactoryBeanName(original.getFactoryBeanName()); setFactoryMethodName(original.getFactoryMethodName()); setScope(original.getScope()); setAbstract(original.isAbstract()); setLazyInit(original.isLazyInit()); setRole(original.getRole()); setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues())); setPropertyValues(new MutablePropertyValues(original.getPropertyValues())); setSource(original.getSource()); copyAttributesFrom(original); if (original instanceof AbstractBeanDefinition) { AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original; if (originalAbd.hasBeanClass()) { setBeanClass(originalAbd.getBeanClass()); } setAutowireMode(originalAbd.getAutowireMode()); setDependencyCheck(originalAbd.getDependencyCheck()); setDependsOn(originalAbd.getDependsOn()); setAutowireCandidate(originalAbd.isAutowireCandidate()); copyQualifiersFrom(originalAbd); setPrimary(originalAbd.isPrimary()); setInitMethodName(originalAbd.getInitMethodName()); setEnforceInitMethod(originalAbd.isEnforceInitMethod()); setDestroyMethodName(originalAbd.getDestroyMethodName()); setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod()); setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides())); setSynthetic(originalAbd.isSynthetic()); setResource(originalAbd.getResource()); } else { setResourceDescription(original.getResourceDescription()); } } /** * Override settings in this bean definition (assumably a copied parent * from a parent-child inheritance relationship) from the given bean * definition (assumably the child). * @deprecated since Spring 2.5, in favor of {@link #overrideFrom(BeanDefinition)} */ public void overrideFrom(AbstractBeanDefinition other) { overrideFrom((BeanDefinition) other); } /** * Override settings in this bean definition (assumably a copied parent * from a parent-child inheritance relationship) from the given bean * definition (assumably the child). * <ul> * <li>Will override beanClass if specified in the given bean definition. * <li>Will always take <code>abstract</code>, <code>scope</code>, * <code>lazyInit</code>, <code>autowireMode</code>, <code>dependencyCheck</code>, * and <code>dependsOn</code> from the given bean definition. * <li>Will add <code>constructorArgumentValues</code>, <code>propertyValues</code>, * <code>methodOverrides</code> from the given bean definition to existing ones. * <li>Will override <code>factoryBeanName</code>, <code>factoryMethodName</code>, * <code>initMethodName</code>, and <code>destroyMethodName</code> if specified * in the given bean definition. * </ul> */ public void overrideFrom(BeanDefinition other) { if (other.getBeanClassName() != null) { setBeanClassName(other.getBeanClassName()); } if (other.getFactoryBeanName() != null) { setFactoryBeanName(other.getFactoryBeanName()); } if (other.getFactoryMethodName() != null) { setFactoryMethodName(other.getFactoryMethodName()); } setScope(other.getScope()); setAbstract(other.isAbstract()); setLazyInit(other.isLazyInit()); setRole(other.getRole()); getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues()); getPropertyValues().addPropertyValues(other.getPropertyValues()); setSource(other.getSource()); copyAttributesFrom(other); if (other instanceof AbstractBeanDefinition) { AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other; if (otherAbd.hasBeanClass()) { setBeanClass(otherAbd.getBeanClass()); } setAutowireCandidate(otherAbd.isAutowireCandidate()); setAutowireMode(otherAbd.getAutowireMode()); copyQualifiersFrom(otherAbd); setPrimary(otherAbd.isPrimary()); setDependencyCheck(otherAbd.getDependencyCheck()); setDependsOn(otherAbd.getDependsOn()); if (otherAbd.getInitMethodName() != null) { setInitMethodName(otherAbd.getInitMethodName()); setEnforceInitMethod(otherAbd.isEnforceInitMethod()); } if (otherAbd.getDestroyMethodName() != null) { setDestroyMethodName(otherAbd.getDestroyMethodName()); setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod()); } getMethodOverrides().addOverrides(otherAbd.getMethodOverrides()); setSynthetic(otherAbd.isSynthetic()); setResource(otherAbd.getResource()); } else { setResourceDescription(other.getResourceDescription()); } } /** * Apply the provided default values to this bean. * @param defaults the defaults to apply */ public void applyDefaults(BeanDefinitionDefaults defaults) { setLazyInit(defaults.isLazyInit()); setDependencyCheck(defaults.getDependencyCheck()); setAutowireMode(defaults.getAutowireMode()); setInitMethodName(defaults.getInitMethodName()); setEnforceInitMethod(false); setDestroyMethodName(defaults.getDestroyMethodName()); setEnforceDestroyMethod(false); } /** * Return whether this definition specifies a bean class. */ public boolean hasBeanClass() { return (this.beanClass instanceof Class); } /** * Specify the class for this bean. */ public void setBeanClass(Class beanClass) { this.beanClass = beanClass; } /** * Return the class of the wrapped bean, if already resolved. * @return the bean class, or <code>null</code> if none defined * @throws IllegalStateException if the bean definition does not define a bean class, * or a specified bean class name has not been resolved into an actual Class */ public Class getBeanClass() throws IllegalStateException { Object beanClassObject = this.beanClass; if (beanClassObject == null) { throw new IllegalStateException("No bean class specified on bean definition"); } if (!(beanClassObject instanceof Class)) { throw new IllegalStateException( "Bean class name [" + beanClassObject + "] has not been resolved into an actual Class"); } return (Class) beanClassObject; } public void setBeanClassName(String beanClassName) { this.beanClass = beanClassName; } public String getBeanClassName() { Object beanClassObject = this.beanClass; if (beanClassObject instanceof Class) { return ((Class) beanClassObject).getName(); } else { return (String) beanClassObject; } } /** * Determine the class of the wrapped bean, resolving it from a * specified class name if necessary. Will also reload a specified * Class from its name when called with the bean class already resolved. * @param classLoader the ClassLoader to use for resolving a (potential) class name * @return the resolved bean class * @throws ClassNotFoundException if the class name could be resolved */ public Class resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException { String className = getBeanClassName(); if (className == null) { return null; } Class resolvedClass = ClassUtils.forName(className, classLoader); this.beanClass = resolvedClass; return resolvedClass; } /** * Set the name of the target scope for the bean. * <p>Default is "singleton"; the out-of-the-box alternative is "prototype". * Extended bean factories might support further scopes. * @see #SCOPE_SINGLETON * @see #SCOPE_PROTOTYPE */ public void setScope(String scope) { Assert.notNull(scope, "Scope must not be null"); this.scope = scope; this.singleton = SCOPE_SINGLETON.equals(scope); this.prototype = SCOPE_PROTOTYPE.equals(scope); } /** * Return the name of the target scope for the bean. */ public String getScope() { return this.scope; } /** * Set if this a <b>Singleton</b>, with a single, shared instance returned * on all calls. In case of "false", the BeanFactory will apply the <b>Prototype</b> * design pattern, with each caller requesting an instance getting an independent * instance. How this is exactly defined will depend on the BeanFactory. * <p>"Singletons" are the commoner type, so the default is "true". * Note that as of Spring 2.0, this flag is just an alternative way to * specify scope="singleton" or scope="prototype". * @deprecated since Spring 2.5, in favor of {@link #setScope} * @see #setScope * @see #SCOPE_SINGLETON * @see #SCOPE_PROTOTYPE */ public void setSingleton(boolean singleton) { this.scope = (singleton ? SCOPE_SINGLETON : SCOPE_PROTOTYPE); this.singleton = singleton; this.prototype = !singleton; } /** * Return whether this a <b>Singleton</b>, with a single shared instance * returned from all calls. * @see #SCOPE_SINGLETON */ public boolean isSingleton() { return this.singleton; } /** * Return whether this a <b>Prototype</b>, with an independent instance * returned for each call. * @see #SCOPE_PROTOTYPE */ public boolean isPrototype() { return this.prototype; } /** * Set if this bean is "abstract", i.e. not meant to be instantiated itself but * rather just serving as parent for concrete child bean definitions. * <p>Default is "false". Specify true to tell the bean factory to not try to * instantiate that particular bean in any case. */ public void setAbstract(boolean abstractFlag) { this.abstractFlag = abstractFlag; } /** * Return whether this bean is "abstract", i.e. not meant to be instantiated * itself but rather just serving as parent for concrete child bean definitions. */ public boolean isAbstract() { return this.abstractFlag; } /** * Set whether this bean should be lazily initialized. * <p>If <code>false</code>, the bean will get instantiated on startup by bean * factories that perform eager initialization of singletons. */ public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; } /** * Return whether this bean should be lazily initialized, i.e. not * eagerly instantiated on startup. Only applicable to a singleton bean. */ public boolean isLazyInit() { return this.lazyInit; } /** * Set the autowire mode. This determines whether any automagical detection * and setting of bean references will happen. Default is AUTOWIRE_NO, * which means there's no autowire. * @param autowireMode the autowire mode to set. * Must be one of the constants defined in this class. * @see #AUTOWIRE_NO * @see #AUTOWIRE_BY_NAME * @see #AUTOWIRE_BY_TYPE * @see #AUTOWIRE_CONSTRUCTOR * @see #AUTOWIRE_AUTODETECT */ public void setAutowireMode(int autowireMode) { this.autowireMode = autowireMode; } /** * Return the autowire mode as specified in the bean definition. */ public int getAutowireMode() { return this.autowireMode; } /** * Return the resolved autowire code, * (resolving AUTOWIRE_AUTODETECT to AUTOWIRE_CONSTRUCTOR or AUTOWIRE_BY_TYPE). * @see #AUTOWIRE_AUTODETECT * @see #AUTOWIRE_CONSTRUCTOR * @see #AUTOWIRE_BY_TYPE */ public int getResolvedAutowireMode() { if (this.autowireMode == AUTOWIRE_AUTODETECT) { // Work out whether to apply setter autowiring or constructor autowiring. // If it has a no-arg constructor it's deemed to be setter autowiring, // otherwise we'll try constructor autowiring. Constructor[] constructors = getBeanClass().getConstructors(); for (int i = 0; i < constructors.length; i++) { if (constructors[i].getParameterTypes().length == 0) { return AUTOWIRE_BY_TYPE; } } return AUTOWIRE_CONSTRUCTOR; } else { return this.autowireMode; } } /** * Set the dependency check code. * @param dependencyCheck the code to set. * Must be one of the four constants defined in this class. * @see #DEPENDENCY_CHECK_NONE * @see #DEPENDENCY_CHECK_OBJECTS * @see #DEPENDENCY_CHECK_SIMPLE * @see #DEPENDENCY_CHECK_ALL */ public void setDependencyCheck(int dependencyCheck) { this.dependencyCheck = dependencyCheck; } /** * Return the dependency check code. */ public int getDependencyCheck() { return this.dependencyCheck; } /** * Set the names of the beans that this bean depends on being initialized. * The bean factory will guarantee that these beans get initialized before. * <p>Note that dependencies are normally expressed through bean properties or * constructor arguments. This property should just be necessary for other kinds * of dependencies like statics (*ugh*) or database preparation on startup. */ public void setDependsOn(String[] dependsOn) { this.dependsOn = dependsOn; } /** * Return the bean names that this bean depends on. */ public String[] getDependsOn() { return this.dependsOn; } /** * Set whether this bean is a candidate for getting autowired into some other bean. */ public void setAutowireCandidate(boolean autowireCandidate) { this.autowireCandidate = autowireCandidate; } /** * Return whether this bean is a candidate for getting autowired into some other bean. */ public boolean isAutowireCandidate() { return this.autowireCandidate; } /** * Register a qualifier to be used for autowire candidate resolution, * keyed by the qualifier's type name. * @see AutowireCandidateQualifier#getTypeName() */ public void addQualifier(AutowireCandidateQualifier qualifier) { this.qualifiers.put(qualifier.getTypeName(), qualifier); } /** * Return whether this bean has the specified qualifier. */ public boolean hasQualifier(String typeName) { return this.qualifiers.keySet().contains(typeName); } /** * Return the qualifier mapped to the provided type name. */ public AutowireCandidateQualifier getQualifier(String typeName) { return (AutowireCandidateQualifier) this.qualifiers.get(typeName); } /** * Return all registered qualifiers. * @return the Set of {@link AutowireCandidateQualifier} objects. */ public Set getQualifiers() { return new LinkedHashSet(this.qualifiers.values()); } /** * Copy the qualifiers from the supplied AbstractBeanDefinition to this bean definition. * @param source the AbstractBeanDefinition to copy from */ protected void copyQualifiersFrom(AbstractBeanDefinition source) { Assert.notNull(source, "Source must not be null"); this.qualifiers.putAll(source.qualifiers); } /** * Set whether this bean is a primary autowire candidate. * If this value is true for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ public void setPrimary(boolean primary) { this.primary = primary; } /** * Return whether this bean is a primary autowire candidate. * If this value is true for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ public boolean isPrimary() { return this.primary; } /** * Specify constructor argument values for this bean. */ public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) { this.constructorArgumentValues = (constructorArgumentValues != null ? constructorArgumentValues : new ConstructorArgumentValues()); } /** * Return constructor argument values for this bean (never <code>null</code>). */ public ConstructorArgumentValues getConstructorArgumentValues() { return this.constructorArgumentValues; } /** * Return if there are constructor argument values defined for this bean. */ public boolean hasConstructorArgumentValues() { return !this.constructorArgumentValues.isEmpty(); } /** * Specify property values for this bean, if any. */ public void setPropertyValues(MutablePropertyValues propertyValues) { this.propertyValues = (propertyValues != null ? propertyValues : new MutablePropertyValues()); } /** * Return property values for this bean (never <code>null</code>). */ public MutablePropertyValues getPropertyValues() { return this.propertyValues; } /** * Specify method overrides for the bean, if any. */ public void setMethodOverrides(MethodOverrides methodOverrides) { this.methodOverrides = (methodOverrides != null ? methodOverrides : new MethodOverrides()); } /** * Return information about methods to be overridden by the IoC * container. This will be empty if there are no method overrides. * Never returns null. */ public MethodOverrides getMethodOverrides() { return this.methodOverrides; } public void setFactoryBeanName(String factoryBeanName) { this.factoryBeanName = factoryBeanName; } public String getFactoryBeanName() { return this.factoryBeanName; } public void setFactoryMethodName(String factoryMethodName) { this.factoryMethodName = factoryMethodName; } public String getFactoryMethodName() { return this.factoryMethodName; } /** * Set the name of the initializer method. The default is <code>null</code> * in which case there is no initializer method. */ public void setInitMethodName(String initMethodName) { this.initMethodName = initMethodName; } /** * Return the name of the initializer method. */ public String getInitMethodName() { return this.initMethodName; } /** * Specify whether or not the configured init method is the default. * Default value is <code>false</code>. * @see #setInitMethodName */ public void setEnforceInitMethod(boolean enforceInitMethod) { this.enforceInitMethod = enforceInitMethod; } /** * Indicate whether the configured init method is the default. * @see #getInitMethodName() */ public boolean isEnforceInitMethod() { return this.enforceInitMethod; } /** * Set the name of the destroy method. The default is <code>null</code> * in which case there is no destroy method. */ public void setDestroyMethodName(String destroyMethodName) { this.destroyMethodName = destroyMethodName; } /** * Return the name of the destroy method. */ public String getDestroyMethodName() { return this.destroyMethodName; } /** * Specify whether or not the configured destroy method is the default. * Default value is <code>false</code>. * @see #setDestroyMethodName */ public void setEnforceDestroyMethod(boolean enforceDestroyMethod) { this.enforceDestroyMethod = enforceDestroyMethod; } /** * Indicate whether the configured destroy method is the default. * @see #getDestroyMethodName */ public boolean isEnforceDestroyMethod() { return this.enforceDestroyMethod; } /** * Set whether this bean definition is 'synthetic', that is, not defined * by the application itself (for example, an infrastructure bean such * as a helper for auto-proxying, created through <code><aop:config></code>). */ public void setSynthetic(boolean synthetic) { this.synthetic = synthetic; } /** * Return whether this bean definition is 'synthetic', that is, * not defined by the application itself. */ public boolean isSynthetic() { return this.synthetic; } /** * Set the role hint for this <code>BeanDefinition</code>. */ public void setRole(int role) { this.role = role; } /** * Return the role hint for this <code>BeanDefinition</code>. */ public int getRole() { return this.role; } /** * Set a human-readable description of this bean definition. */ public void setDescription(String description) { this.description = description; } public String getDescription() { return this.description; } /** * Set the resource that this bean definition came from * (for the purpose of showing context in case of errors). */ public void setResource(Resource resource) { this.resource = resource; } /** * Return the resource that this bean definition came from. */ public Resource getResource() { return this.resource; } /** * Set a description of the resource that this bean definition * came from (for the purpose of showing context in case of errors). */ public void setResourceDescription(String resourceDescription) { this.resource = new DescriptiveResource(resourceDescription); } public String getResourceDescription() { return (this.resource != null ? this.resource.getDescription() : null); } /** * Set the originating (e.g. decorated) BeanDefinition, if any. */ public void setOriginatingBeanDefinition(BeanDefinition originatingBd) { this.resource = new BeanDefinitionResource(originatingBd); } public BeanDefinition getOriginatingBeanDefinition() { return (this.resource instanceof BeanDefinitionResource ? ((BeanDefinitionResource) this.resource).getBeanDefinition() : null); } /** * Validate this bean definition. * @throws BeanDefinitionValidationException in case of validation failure */ public void validate() throws BeanDefinitionValidationException { if (!getMethodOverrides().isEmpty() && getFactoryMethodName() != null) { throw new BeanDefinitionValidationException( "Cannot combine static factory method with method overrides: " + "the static factory method must create the instance"); } if (hasBeanClass()) { prepareMethodOverrides(); } } /** * Validate and prepare the method overrides defined for this bean. * Checks for existence of a method with the specified name. * @throws BeanDefinitionValidationException in case of validation failure */ public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. MethodOverrides methodOverrides = getMethodOverrides(); if (!methodOverrides.isEmpty()) { for (Iterator it = methodOverrides.getOverrides().iterator(); it.hasNext(); ) { MethodOverride mo = (MethodOverride) it.next(); prepareMethodOverride(mo); } } } /** * Validate and prepare the given method override. * Checks for existence of a method with the specified name, * marking it as not overloaded if none found. * @param mo the MethodOverride object to validate * @throws BeanDefinitionValidationException in case of validation failure */ protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); } } /** * Public declaration of Object's <code>clone()</code> method. * Delegates to {@link #cloneBeanDefinition()}. * @see java.lang.Object#clone() */ public Object clone() { return cloneBeanDefinition(); } /** * Clone this bean definition. * To be implemented by concrete subclasses. * @return the cloned bean definition object */ public abstract AbstractBeanDefinition cloneBeanDefinition(); public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof AbstractBeanDefinition)) { return false; } AbstractBeanDefinition that = (AbstractBeanDefinition) other; if (!ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName())) return false; if (!ObjectUtils.nullSafeEquals(this.scope, that.scope)) return false; if (this.abstractFlag != that.abstractFlag) return false; if (this.lazyInit != that.lazyInit) return false; if (this.autowireMode != that.autowireMode) return false; if (this.dependencyCheck != that.dependencyCheck) return false; if (!Arrays.equals(this.dependsOn, that.dependsOn)) return false; if (this.autowireCandidate != that.autowireCandidate) return false; if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) return false; if (this.primary != that.primary) return false; if (!ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues)) return false; if (!ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues)) return false; if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false; if (!ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName)) return false; if (!ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName)) return false; if (!ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName)) return false; if (this.enforceInitMethod != that.enforceInitMethod) return false; if (!ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName)) return false; if (this.enforceDestroyMethod != that.enforceDestroyMethod) return false; if (this.synthetic != that.synthetic) return false; if (this.role != that.role) return false; return super.equals(other); } public int hashCode() { int hashCode = ObjectUtils.nullSafeHashCode(getBeanClassName()); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.scope); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.constructorArgumentValues); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.propertyValues); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryBeanName); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryMethodName); hashCode = 29 * hashCode + super.hashCode(); return hashCode; } public String toString() { StringBuffer sb = new StringBuffer("class ["); sb.append(getBeanClassName()).append("]"); sb.append("; scope=").append(this.scope); sb.append("; abstract=").append(this.abstractFlag); sb.append("; lazyInit=").append(this.lazyInit); sb.append("; autowireMode=").append(this.autowireMode); sb.append("; dependencyCheck=").append(this.dependencyCheck); sb.append("; autowireCandidate=").append(this.autowireCandidate); sb.append("; primary=").append(this.primary); sb.append("; factoryBeanName=").append(this.factoryBeanName); sb.append("; factoryMethodName=").append(this.factoryMethodName); sb.append("; initMethodName=").append(this.initMethodName); sb.append("; destroyMethodName=").append(this.destroyMethodName); if (this.resource != null) { sb.append("; defined in ").append(this.resource.getDescription()); } return sb.toString(); } }