概述
AbstractBeanDefinition
是最终全功能BeanDefinition
实现类的基类,也就是这些类的共同属性和公共逻辑实现。
AbstractBeanDefinition
中并没有太复杂的实现逻辑,而是主要是用于:
- 定义共用的构造函数。
- 定义共用
BeanDefinition
属性以及提供它们的getter/setter
方法。 - 其他一些共用工具方法 : 从另外一个bean定义覆盖当前bean定义,应用初始值等等。
另外AbstractBeanDefinition
继承自BeanMetadataAttributeAccessor
。BeanMetadataAttributeAccessor
为AbstractBeanDefinition
提供了接口AttributeAccessor
定义的属性访问能力以及BeanMetadataElement
定义的源配置对象设置/获取能力。
继承自
AbstractBeanDefinition
的全功能BeanDefinition
实现类有 :
GenericBeanDefinition
RootBeanDefinition
ChildBeanDefinition
源代码解析
package org.springframework.beans.factory.support;
// 省略imports
/**
* 最终全功能BeanDefinition实现类的基类,也就是这些类的共同属性和逻辑实现:
* GenericBeanDefinition,RootBeanDefinition,ChildBeanDefinition.
*
*/
@SuppressWarnings("serial")
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 缺省作用域名称常量定义:"",等价于 singleton
public static final String SCOPE_DEFAULT = "";
/**
* 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
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* use annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
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;
/**
* Constant that indicates the container should attempt to infer the
* #setDestroyMethodName destroy method name for a bean as opposed to
* explicit specification of a method name. The value @value is specifically
* designed to include characters otherwise illegal in a method name, ensuring
* no possibility of collisions with legitimately named methods having the same
* name.
* Currently, the method names detected during destroy method inference
* are "close" and "shutdown", if present on the specific bean class.
*/
public static final String INFER_METHOD = "(inferred)";
// 当前bean定义的beanClass属性,注意并不一定是最终生成的bean所使用的class,
// 可能是 String, 也可能是 Class
@Nullable
private volatile Object beanClass;
// 目标 bean 的作用域,初始化为 "", 相当于 singleton
@Nullable
private String scope = SCOPE_DEFAULT;
// 是否抽象 bean定义
private boolean abstractFlag = false;
// 是否懒初始化
private boolean lazyInit = false;
// 自动装配模式 : 初始化为不要使用自动装配
private int autowireMode = AUTOWIRE_NO;
// 依赖检查 : 初始化为不要做依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
// 被当前bean定义所依赖的bean的名称
@Nullable
private String[] dependsOn;
// 是否作为自动装配候选 , 初始化为 true
private boolean autowireCandidate = true;
// 作为自动装配候选时,是否作为主要候选, 初始化为 false (不作为主要候选)
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
@Nullable
private Supplier<?> instanceSupplier;
// 是否允许访问非公开构造函数,非公开方法
// 该属性主要用于构造函数解析,初始化方法,析构方法解析,bean属性的set/get方法不受该属性影响
private boolean nonPublicAccessAllowed = true;
//调用构造函数时,是否采用宽松匹配
private boolean lenientConstructorResolution = true;
// 工厂bean名称
@Nullable
private String factoryBeanName;
// 工厂方法名称
@Nullable
private String factoryMethodName;
// 构造函数参数值
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
// 属性值,注意这里使用了 MutablePropertyValues , 表示这些属性值在
// 最终被设置到 bean实例之前一直是可以被修改的
@Nullable
private MutablePropertyValues propertyValues;
@Nullable
private MethodOverrides methodOverrides;
// 初始化方法的名称
@Nullable
private String initMethodName;
// 析构方法的名称
@Nullable
private String destroyMethodName;
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
// 是否是一个合成 BeanDefinition,
// 合成 在这里的意思表示这不是一个应用开发人员自己定义的 BeanDefinition, 而是程序
// 自己组装而成的一个 BeanDefinition, 例子 :
// 1. 自动代理的helper bean,一个基础设施bean,因为使用<aop:config> 被自动合成创建;
// 2. bean errorPageRegistrarBeanPostProcessor , Spring boot 自动配置针对Web错误页面的
// 一个bean,这个bean不需要应用开发人员定义,而是框架根据上下文自动合成组装而成;
private boolean synthetic = false;
// 当前bean 定义的角色,初始化为 ROLE_APPLICATION , 提示这是一个应用bean
// 另外还有基础设施bean(仅供框架内部工作使用),和 支持bean
private int role = BeanDefinition.ROLE_APPLICATION;
// human readable,当前bean定义人类可读的描述文本
@Nullable
private String description;
@Nullable
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(@Nullable ConstructorArgumentValues cargs,
@Nullable MutablePropertyValues pvs) {
this.constructorArgumentValues = cargs;
this.propertyValues = pvs;
}
/**
* 深度复制给定的bean定义创建一个新的AbstractBeanDefinition
* @param original the original bean definition to copy from
*/
protected AbstractBeanDefinition(BeanDefinition original) {
setParentName(original.getParentName());
setBeanClassName(original.getBeanClassName());
setScope(original.getScope());
setAbstract(original.isAbstract());
setLazyInit(original.isLazyInit());
setFactoryBeanName(original.getFactoryBeanName());
setFactoryMethodName(original.getFactoryMethodName());
setRole(original.getRole());
setSource(original.getSource());
copyAttributesFrom(original);
if (original instanceof AbstractBeanDefinition) {
AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original;
if (originalAbd.hasBeanClass()) {
setBeanClass(originalAbd.getBeanClass());
}
if (originalAbd.hasConstructorArgumentValues()) {
setConstructorArgumentValues(
new ConstructorArgumentValues(original.getConstructorArgumentValues()));
}
if (originalAbd.hasPropertyValues()) {
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
}
if (originalAbd.hasMethodOverrides()) {
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
}
setAutowireMode(originalAbd.getAutowireMode());
setDependencyCheck(originalAbd.getDependencyCheck());
setDependsOn(originalAbd.getDependsOn());
setAutowireCandidate(originalAbd.isAutowireCandidate());
setPrimary(originalAbd.isPrimary());
copyQualifiersFrom(originalAbd);
setInstanceSupplier(originalAbd.getInstanceSupplier());
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
setInitMethodName(originalAbd.getInitMethodName());
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
setDestroyMethodName(originalAbd.getDestroyMethodName());
setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
setSynthetic(originalAbd.isSynthetic());
setResource(originalAbd.getResource());
}
else {
setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
setResourceDescription(original.getResourceDescription());
}
}
/**
* Override settings in this bean definition (presumably a copied parent
* from a parent-child inheritance relationship) from the given bean
* definition (presumably the child).
*
* 本方法的一个主要用途是用在根据bean定义之间的父子关系生成最终merged的孩子bean定义对象:
* 此时先使用双亲bean定义生成一个RootBeanDefinition,然后调用该RootBeanDefinition
* 对象的overrideFrom(other)方法,这里other就是child bean定义,然后这个RootBeanDefinition
* 就是一个继承自双亲bean定义又符合原始child bean定义的一个最终被使用的BeanDefinition了。
*
* 1. Will override beanClass if specified in the given bean definition.
*
* 2. Will always take abstract, scope,lazyInit, autowireMode, dependencyCheck,
* and dependsOn from the given bean definition.
*
* 3. Will add constructorArgumentValues, propertyValues,
* methodOverrides from the given bean definition to existing ones.
*
* 4. Will override factoryBeanName, factoryMethodName,initMethodName,
* and destroyMethodName if specified in the given bean definition.
*
*/
public void overrideFrom(BeanDefinition other) {
if (StringUtils.hasLength(other.getBeanClassName())) {
setBeanClassName(other.getBeanClassName());
}
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
setAbstract(other.isAbstract());
setLazyInit(other.isLazyInit());
if (StringUtils.hasLength(other.getFactoryBeanName())) {
setFactoryBeanName(other.getFactoryBeanName());
}
if (StringUtils.hasLength(other.getFactoryMethodName())) {
setFactoryMethodName(other.getFactoryMethodName());
}
setRole(other.getRole());
setSource(other.getSource());
copyAttributesFrom(other);
if (other instanceof AbstractBeanDefinition) {
AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
if (otherAbd.hasBeanClass()) {
setBeanClass(otherAbd.getBeanClass());
}
if (otherAbd.hasConstructorArgumentValues()) {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
}
if (otherAbd.hasPropertyValues()) {
getPropertyValues().addPropertyValues(other.getPropertyValues());
}
if (otherAbd.hasMethodOverrides()) {
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
}
setAutowireMode(otherAbd.getAutowireMode());
setDependencyCheck(otherAbd.getDependencyCheck());
setDependsOn(otherAbd.getDependsOn());
setAutowireCandidate(otherAbd.isAutowireCandidate());
setPrimary(otherAbd.isPrimary());
copyQualifiersFrom(otherAbd);
setInstanceSupplier(otherAbd.getInstanceSupplier());
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
if (otherAbd.getInitMethodName() != null) {
setInitMethodName(otherAbd.getInitMethodName());
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
}
if (otherAbd.getDestroyMethodName() != null) {
setDestroyMethodName(otherAbd.getDestroyMethodName());
setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
}
setSynthetic(otherAbd.isSynthetic());
setResource(otherAbd.getResource());
}
else {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
getPropertyValues().addPropertyValues(other.getPropertyValues());
setResourceDescription(other.getResourceDescription());
}
}
/**
* Apply the provided default values to this bean.
* 使用缺省值定义进行当前bean定义的初始化
* @param defaults the defaults to apply
*/
public void applyDefaults(BeanDefinitionDefaults defaults) {
setLazyInit(defaults.isLazyInit());
setAutowireMode(defaults.getAutowireMode());
setDependencyCheck(defaults.getDependencyCheck());
setInitMethodName(defaults.getInitMethodName());
setEnforceInitMethod(false);
setDestroyMethodName(defaults.getDestroyMethodName());
setEnforceDestroyMethod(false);
}
/**
* Specify the bean class name of this bean definition.
*/
@Override
public void setBeanClassName(@Nullable String beanClassName) {
this.beanClass = beanClassName;
}
/**
* Return the current bean class name of this bean definition.
*/
@Override
@Nullable
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}
/**
* Specify the class for this bean.
*/
public void setBeanClass(@Nullable Class<?> beanClass) {
this.beanClass = beanClass;
}
/**
* Return the class of the wrapped bean, if already resolved.
* @return the bean class, or null 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;
}
/**
* Return whether this definition specifies a bean class.
*/
public boolean hasBeanClass() {
return (this.beanClass instanceof Class);
}
/**
* 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
*/
@Nullable
public Class<?> resolveBeanClass(@Nullable 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.
* The default is singleton status, although this is only applied once
* a bean definition becomes active in the containing factory. A bean
* definition may eventually inherit its scope from a parent bean definition.
* For this reason, the default scope name is an empty string (i.e., ""),
* with singleton status being assumed until a resolved scope is set.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
@Override
public void setScope(@Nullable String scope) {
this.scope = scope;
}
/**
* Return the name of the target scope for the bean.
*/
@Override
@Nullable
public String getScope() {
return this.scope;
}
/**
* Return whether this a Singleton, with a single shared instance
* returned from all calls. 作用域是否单例 singleton
* @see #SCOPE_SINGLETON
*/
@Override
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);
}
/**
* Return whether this a Prototype, with an independent instance
* returned for each call. 作用域是否 prototype, 每次调用getBean()生成一个新的bean实例
* @see #SCOPE_PROTOTYPE
*/
@Override
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(this.scope);
}
/**
* 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.
* 是否抽象bean定义,抽象bean定义表示该bean定义不用于被实例化,而仅仅作为
* 最终实现子bean定义的双亲。
*/
@Override
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.
*/
@Override
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.
*/
@Override
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 (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 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 first.
* <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.
*/
@Override
public void setDependsOn(@Nullable String... dependsOn) {
this.dependsOn = dependsOn;
}
/**
* Return the bean names that this bean depends on.
*/
@Override
@Nullable
public String[] getDependsOn() {
return this.dependsOn;
}
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
* <p>Note that this flag is designed to only affect type-based autowiring.
* It does not affect explicit references by name, which will get resolved even
* if the specified bean is not marked as an autowire candidate. As a consequence,
* autowiring by name will nevertheless inject a bean if the name matches.
* @see #AUTOWIRE_BY_TYPE
* @see #AUTOWIRE_BY_NAME
*/
@Override
public void setAutowireCandidate(boolean autowireCandidate) {
this.autowireCandidate = autowireCandidate;
}
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
*/
@Override
public boolean isAutowireCandidate() {
return this.autowireCandidate;
}
/**
* Set whether this bean is a primary autowire candidate.
* <p>If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
@Override
public void setPrimary(boolean primary) {
this.primary = primary;
}
/**
* Return whether this bean is a primary autowire candidate.
*/
@Override
public boolean isPrimary() {
return this.primary;
}
/**
* 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.
*/
@Nullable
public AutowireCandidateQualifier getQualifier(String typeName) {
return this.qualifiers.get(typeName);
}
/**
* Return all registered qualifiers.
* @return the Set of AutowireCandidateQualifier objects.
*/
public Set<AutowireCandidateQualifier> 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
*/
public void copyQualifiersFrom(AbstractBeanDefinition source) {
Assert.notNull(source, "Source must not be null");
this.qualifiers.putAll(source.qualifiers);
}
/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
* @see #setConstructorArgumentValues(ConstructorArgumentValues)
* @see #setPropertyValues(MutablePropertyValues)
*/
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
/**
* Return a callback for creating an instance of the bean, if any.
* @since 5.0
*/
@Nullable
public Supplier<?> getInstanceSupplier() {
return this.instanceSupplier;
}
/**
* Specify whether to allow access to non-public constructors and methods,
* for the case of externalized metadata pointing to those. The default is
* true; switch this to false for public access only.
* This applies to constructor resolution, factory method resolution,
* and also init/destroy methods. Bean property accessors have to be public
* in any case and are not affected by this setting.
* Note that annotation-driven configuration will still access non-public
* members as far as they have been annotated. This setting applies to
* externalized metadata in this bean definition only.
*/
public void setNonPublicAccessAllowed(boolean nonPublicAccessAllowed) {
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
}
/**
* Return whether to allow access to non-public constructors and methods.
*/
public boolean isNonPublicAccessAllowed() {
return this.nonPublicAccessAllowed;
}
/**
* Specify whether to resolve constructors in lenient mode ( true,
* which is the default) or to switch to strict resolution (throwing an exception
* in case of ambiguous constructors that all match when converting the arguments,
* whereas lenient mode would use the one with the 'closest' type matches).
*/
public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
this.lenientConstructorResolution = lenientConstructorResolution;
}
/**
* Return whether to resolve constructors in lenient mode or in strict mode.
*/
public boolean isLenientConstructorResolution() {
return this.lenientConstructorResolution;
}
/**
* Specify the factory bean to use, if any.
* This the name of the bean to call the specified factory method on.
* @see #setFactoryMethodName
*/
@Override
public void setFactoryBeanName(@Nullable String factoryBeanName) {
this.factoryBeanName = factoryBeanName;
}
/**
* Return the factory bean name, if any.
*/
@Override
@Nullable
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 method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
@Override
public void setFactoryMethodName(@Nullable String factoryMethodName) {
this.factoryMethodName = factoryMethodName;
}
/**
* Return a factory method, if any.
*/
@Override
@Nullable
public String getFactoryMethodName() {
return this.factoryMethodName;
}
/**
* Specify constructor argument values for this bean.
*/
public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) {
this.constructorArgumentValues = constructorArgumentValues;
}
/**
* Return constructor argument values for this bean (never null).
*/
@Override
public ConstructorArgumentValues getConstructorArgumentValues() {
if (this.constructorArgumentValues == null) {
this.constructorArgumentValues = new ConstructorArgumentValues();
}
return this.constructorArgumentValues;
}
/**
* Return if there are constructor argument values defined for this bean.
*/
@Override
public boolean hasConstructorArgumentValues() {
return (this.constructorArgumentValues != null && !this.constructorArgumentValues.isEmpty());
}
/**
* Specify property values for this bean, if any.
*/
public void setPropertyValues(MutablePropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
/**
* Return property values for this bean (never null).
*/
@Override
public MutablePropertyValues getPropertyValues() {
if (this.propertyValues == null) {
this.propertyValues = new MutablePropertyValues();
}
return this.propertyValues;
}
/**
* Return if there are property values values defined for this bean.
* @since 5.0.2
*/
@Override
public boolean hasPropertyValues() {
return (this.propertyValues != null && !this.propertyValues.isEmpty());
}
/**
* Specify method overrides for the bean, if any.
*/
public void setMethodOverrides(MethodOverrides methodOverrides) {
this.methodOverrides = methodOverrides;
}
/**
* Return information about methods to be overridden by the IoC
* container. This will be empty if there are no method overrides.
* <p>Never returns null.
*/
public MethodOverrides getMethodOverrides() {
if (this.methodOverrides == null) {
this.methodOverrides = new MethodOverrides();
}
return this.methodOverrides;
}
/**
* Return if there are method overrides defined for this bean.
* @since 5.0.2
*/
public boolean hasMethodOverrides() {
return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
}
/**
* Set the name of the initializer method.
* <p>The default is null in which case there is no initializer method.
*/
@Override
public void setInitMethodName(@Nullable String initMethodName) {
this.initMethodName = initMethodName;
}
/**
* Return the name of the initializer method.
*/
@Override
@Nullable
public String getInitMethodName() {
return this.initMethodName;
}
/**
* Specify whether or not the configured init method is the default.
* The 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.
*/
@Override
public void setDestroyMethodName(@Nullable String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
/**
* Return the name of the destroy method.
*/
@Override
@Nullable
public String getDestroyMethodName() {
return this.destroyMethodName;
}
/**
* Specify whether or not the configured destroy method is the default.
* The 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 the role hint for this BeanDefinition.
*/
@Override
public void setRole(int role) {
this.role = role;
}
/**
* Return the role hint for this BeanDefinition.
*/
@Override
public int getRole() {
return this.role;
}
/**
* Set a human-readable description of this bean definition.
*/
@Override
public void setDescription(@Nullable String description) {
this.description = description;
}
/**
* Return a human-readable description of this bean definition.
*/
@Override
@Nullable
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(@Nullable Resource resource) {
this.resource = resource;
}
/**
* Return the resource that this bean definition came from.
*/
@Nullable
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(@Nullable String resourceDescription) {
this.resource = (resourceDescription != null ? new DescriptiveResource(resourceDescription) : null);
}
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Override
@Nullable
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);
}
/**
* Return the originating BeanDefinition, or null if none.
* Allows for retrieving the decorated bean definition, if any.
* Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
@Override
@Nullable
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 (hasMethodOverrides() && 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.
if (hasMethodOverrides()) {
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
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 clone() method.
* Delegates to #cloneBeanDefinition().
* @see Object#clone()
*/
@Override
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();
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AbstractBeanDefinition)) {
return false;
}
AbstractBeanDefinition that = (AbstractBeanDefinition) other;
boolean rtn = ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName());
rtn = rtn &= ObjectUtils.nullSafeEquals(this.scope, that.scope);
rtn = rtn &= this.abstractFlag == that.abstractFlag;
rtn = rtn &= this.lazyInit == that.lazyInit;
rtn = rtn &= this.autowireMode == that.autowireMode;
rtn = rtn &= this.dependencyCheck == that.dependencyCheck;
rtn = rtn &= Arrays.equals(this.dependsOn, that.dependsOn);
rtn = rtn &= this.autowireCandidate == that.autowireCandidate;
rtn = rtn &= ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers);
rtn = rtn &= this.primary == that.primary;
rtn = rtn &= this.nonPublicAccessAllowed == that.nonPublicAccessAllowed;
rtn = rtn &= this.lenientConstructorResolution == that.lenientConstructorResolution;
rtn = rtn &= ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues);
rtn = rtn &= ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues);
rtn = rtn &= ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides);
rtn = rtn &= ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName);
rtn = rtn &= ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName);
rtn = rtn &= ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName);
rtn = rtn &= this.enforceInitMethod == that.enforceInitMethod;
rtn = rtn &= ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName);
rtn = rtn &= this.enforceDestroyMethod == that.enforceDestroyMethod;
rtn = rtn &= this.synthetic == that.synthetic;
rtn = rtn &= this.role == that.role;
return rtn && super.equals(other);
}
@Override
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;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("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();
}
}
相关文章
Spring的bean定义 1 : 基础建模–接口BeanDefinition
Spring的bean定义 2 : 通用bean定义逻辑 – AbstractBeanDefinition
Spring的bean定义 3 : BeanDefinition实现类例子演示
Spring的bean定义 4 : 合并了的bean定义–MergedBeanDefinition