All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.beans.factory.support.AbstractBeanDefinition Maven / Gradle / Ivy

There is a newer version: 5.3.34
Show newest version
/*
 * Copyright 2002-2007 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 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.AttributeAccessorSupport;
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}.
 *
 * 

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 * @see RootBeanDefinition * @see ChildBeanDefinition */ public abstract class AbstractBeanDefinition extends AttributeAccessorSupport implements BeanDefinition { /** * 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 Object beanClass; private String scope = SCOPE_SINGLETON; private boolean singleton = true; private boolean prototype = false; private boolean abstractFlag = false; private boolean lazyInit = false; private boolean autowireCandidate = true; private int autowireMode = AUTOWIRE_NO; private int dependencyCheck = DEPENDENCY_CHECK_NONE; private String[] dependsOn; 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 String resourceDescription; private Object source; private int role = BeanDefinition.ROLE_APPLICATION; /** * 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 */ protected AbstractBeanDefinition(AbstractBeanDefinition original) { this.beanClass = original.beanClass; setScope(original.getScope()); setAbstract(original.isAbstract()); setLazyInit(original.isLazyInit()); setAutowireCandidate(original.isAutowireCandidate()); setAutowireMode(original.getAutowireMode()); setDependencyCheck(original.getDependencyCheck()); setDependsOn(original.getDependsOn()); setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues())); setPropertyValues(new MutablePropertyValues(original.getPropertyValues())); setMethodOverrides(new MethodOverrides(original.getMethodOverrides())); setFactoryBeanName(original.getFactoryBeanName()); setFactoryMethodName(original.getFactoryMethodName()); setInitMethodName(original.getInitMethodName()); setEnforceInitMethod(original.isEnforceInitMethod()); setDestroyMethodName(original.getDestroyMethodName()); setEnforceDestroyMethod(original.isEnforceDestroyMethod()); setSynthetic(original.isSynthetic()); setResourceDescription(original.getResourceDescription()); setSource(original.getSource()); setRole(original.getRole()); copyAttributesFrom(original); } /** * Override settings in this bean definition (assumably a copied parent * from a parent-child inheritance relationship) from the given bean * definition (assumably the child). *

    *
  • Will override beanClass if specified in the given bean definition. *
  • Will always take abstract, singleton, lazyInit, autowireMode, * dependencyCheck, dependsOn from the given bean definition. *
  • Will add constructorArgumentValues, propertyValues, methodOverrides * from the given bean definition to existing ones. *
  • Will override factoryBeanName, factoryMethodName, initMethodName, * destroyMethodName if specified in the given bean definition. *
*/ public void overrideFrom(AbstractBeanDefinition other) { if (other.beanClass != null) { this.beanClass = other.beanClass; } setScope(other.getScope()); setAbstract(other.isAbstract()); setLazyInit(other.isLazyInit()); setAutowireCandidate(other.isAutowireCandidate()); setAutowireMode(other.getAutowireMode()); setDependencyCheck(other.getDependencyCheck()); setDependsOn(other.getDependsOn()); getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues()); getPropertyValues().addPropertyValues(other.getPropertyValues()); getMethodOverrides().addOverrides(other.getMethodOverrides()); if (other.getFactoryBeanName() != null) { setFactoryBeanName(other.getFactoryBeanName()); } if (other.getFactoryMethodName() != null) { setFactoryMethodName(other.getFactoryMethodName()); } if (other.getInitMethodName() != null) { setInitMethodName(other.getInitMethodName()); setEnforceInitMethod(other.isEnforceInitMethod()); } if (other.getDestroyMethodName() != null) { setDestroyMethodName(other.getDestroyMethodName()); setEnforceDestroyMethod(other.isEnforceDestroyMethod()); } setSynthetic(other.isSynthetic()); setResourceDescription(other.getResourceDescription()); setSource(other.getSource()); setRole(other.getRole()); copyAttributesFrom(other); } /** * 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. * @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 { if (this.beanClass == null) { throw new IllegalStateException("No bean class specified on bean definition"); } if (!(this.beanClass instanceof Class)) { throw new IllegalStateException( "Bean class name [" + this.beanClass + "] has not been resolved into an actual Class"); } return (Class) this.beanClass; } /** * Specify the class name for this bean. */ public void setBeanClassName(String beanClassName) { this.beanClass = beanClassName; } /** * Return the class name of the wrapped bean. */ public String getBeanClassName() { if (this.beanClass instanceof Class) { return ((Class) this.beanClass).getName(); } else { return (String) this.beanClass; } } /** * 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 { if (this.beanClass == null) { return null; } Class resolvedClass = ClassUtils.forName(getBeanClassName(), classLoader); this.beanClass = resolvedClass; return resolvedClass; } /** * Set the name of the target scope for the bean. *

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 Singleton, with a single, shared instance returned * on all calls. In case of "false", the BeanFactory will apply the Prototype * design pattern, with each caller requesting an instance getting an independent * instance. How this is exactly defined will depend on the BeanFactory. *

"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". * @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 Singleton, with a single shared instance * returned from all calls. * @see #SCOPE_SINGLETON */ public boolean isSingleton() { return this.singleton; } /** * Return whether this a Prototype, 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. *

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. *

If false, 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 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; } /** * 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. *

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; } /** * 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 null). */ 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 null). */ 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; } /** * Specify the factory bean to use, if any. */ public void setFactoryBeanName(String factoryBeanName) { this.factoryBeanName = factoryBeanName; } /** * Returns the factory bean name, if any. */ public String getFactoryBeanName() { return this.factoryBeanName; } /** * Specify a factory method, if any. This method will be invoked with * constructor arguments, or with no arguments if none are specified. * The static method will be invoked on the specifed factory bean, * if any, or on the local bean class else. * @param factoryMethodName static factory method name, or null if * normal constructor creation should be used * @see #getBeanClass */ public void setFactoryMethodName(String factoryMethodName) { this.factoryMethodName = factoryMethodName; } /** * Return a factory method, if any. */ public String getFactoryMethodName() { return this.factoryMethodName; } /** * Set the name of the initializer method. The default is null * 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 false. * @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 null * 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 false. * @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 <aop:config>). */ 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 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.resourceDescription = resourceDescription; } /** * Return a description of the resource that this bean definition * came from. */ public String getResourceDescription() { return this.resourceDescription; } /** * Set the configuration source Object for this metadata element. *

The exact type of the object will depend on the configuration mechanism used. */ public void setSource(Object source) { this.source = source; } public Object getSource() { return this.source; } /** * Set the role hint for this BeanDefinition. */ public void setRole(int role) { this.role = role; } /** * Return the role hint for this BeanDefinition. */ public int getRole() { return this.role; } /** * 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. for (Iterator it = getMethodOverrides().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 boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof AbstractBeanDefinition)) { return false; } AbstractBeanDefinition that = (AbstractBeanDefinition) other; if (!ObjectUtils.nullSafeEquals(this.beanClass, that.beanClass)) 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.autowireCandidate != that.autowireCandidate) 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 (!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 (!ObjectUtils.nullSafeEquals(this.resourceDescription, that.resourceDescription)) return false; if (!ObjectUtils.nullSafeEquals(this.source, that.source)) return false; if (this.role != that.role) return false; return super.equals(other); } public int hashCode() { int hashCode = ObjectUtils.nullSafeHashCode(this.beanClass); 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("; autowireCandidate=").append(this.autowireCandidate); sb.append("; autowireMode=").append(this.autowireMode); sb.append("; dependencyCheck=").append(this.dependencyCheck); 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.resourceDescription != null) { sb.append("; defined in ").append(this.resourceDescription); } return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy