spring源码学习(1) --BeanDefinition学习

原创 2016年12月13日 15:39:07

BeanDefinition

BeanDefinition作为定义springBean文件中bean的接口,可以说是bean的抽象数据结构,它包括属性参数,构造器参数,以及其他具体的参数。

<bean id="person" class="com.demo.People">
    <property name="age" value="20"/>
    <property name="knife" ref="knife"/>
</bean>

以上为使用setter注入的bean,最常见的bean,bean的属性有很多,
我们可以在root<beans>里面定义,也可以在子<bean>定义来覆盖。

<bean id="people" class="" parent="" lazy-init=""
init-method="" destroy-method="" autowire="" scope=""/>

这些属性,都在注入过程中,进行设置。

BeanDefinition类介绍

实现接口

  1. AttributeAccessor 该接口定义了与其它对象的(元数据)进行连接和访问的约定,即对属性的修改,包括获取,设置,删除。

    其实现类 AttributeAccessorSupport是对AttributeAccessor接口方法的具体实现,它维护了一个 map Map<String, Object>容器,用来对属性进行增删改查。

  2. BeanMetadataElement Bean元对象 持有的配置元素 可以通过getSource()方法来获取。
    其中BeanMetadataAttribute实现该接口,用来持有key-value元素,保存属性值。

继承结构

  1. AbstractBeanDefiniton,采用配置文件生成的抽象类,保存一个bean的所有通用属性,

    • 继承:
      BeanMetadataAttributeAccessor,而他继承AttributeAccessorSupport,并且实现BeanMetadataElement接口,则该类为对BeanDefinition属性进行维护。

    • 接口:
      - BeanDefinition,实现了对bean属性的设置
      - Cloneable,实现了复制功能。

    所有的bean的配置元素都在AbstractBeanDefinition里面定义了,在载入过程中,对其进行维护。

    • 子类
      • ChildBeanDefinition 维护parent属性。
      • GenericBeanDefinition 通用模板,同样维护parent属性,现在有替换掉ChildBeanDefinition的趋势,动态维护fubean
      • RootBeanDefinition A root bean definition is essentially the ‘unified’ bean definition view at runtime.在载入时用到的bean。没有父bean也可以使用。
  2. AnnotatedBeanDefinition ,采用注解的方式生成的Bean结构。

AbstractBeanDefinition类分析

/*
 * Copyright 2002-2009 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.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;
import org.springframework.util.StringUtils;

/**
 * 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 for the default scope name: "", equivalent to singleton status
     * but to be overridden from a parent bean definition (if applicable).
     * 默认作用域
     */
    public static final String SCOPE_DEFAULT = "";


    /**
     * Constant that indicates no autowiring at all.
     * @see #setAutowireMode
     * 自动装配类型  no
     */

    public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

    /**
     * Constant that indicates autowiring bean properties by name.
     * 自动装配类型  byName
     * @see #setAutowireMode
     */
    public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

    /**
     * Constant that indicates autowiring bean properties by type.
     * @see #setAutowireMode
     * 自动装配类型  byType
     */
    public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

    /**
     * Constant that indicates autowiring a constructor.
     * @see #setAutowireMode
     * 自动装配类型 constuctor
     */
    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
     * 自动装配类型  autodetect 自动选择,有默认构造器,则选择byType
     * @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
     * 依赖设置:是否有依赖类 depends-on
     */
    public static final int DEPENDENCY_CHECK_NONE = 0;

    /**
     * Constant that indicates dependency checking for object references.
     * @see #setDependencyCheck
     * 依赖设置:是否有依赖类  无depends-on ref
     */
    public static final int DEPENDENCY_CHECK_OBJECTS = 1;

    /**
     * Constant that indicates dependency checking for "simple" properties.
     * @see #setDependencyCheck
     * @see org.springframework.beans.BeanUtils#isSimpleProperty
     * 依赖设置:是否有依赖类  value依赖
     */
    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;

    //class 类 ,使用反射机制 ,对应class属性
    private volatile Object beanClass;
    //对应 scope属性 protoType singleTon
    private String scope = SCOPE_DEFAULT;

    private boolean singleton = true;

    private boolean prototype = false;
    //对应abstract属性
    private boolean abstractFlag = false;
    //lazy-init 属性
    private boolean lazyInit = false;
    //autowire属性
    private int autowireMode = AUTOWIRE_NO;
    //依赖的类型。
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;
    //依赖的ref
    private String[] dependsOn;
    //是否autowire-candidate 设置
    private boolean autowireCandidate = true;
    //是否primary  ? 是否为候选者shou
    private boolean primary = false;

    //用来维护自动装配所需要的限定类、
    private final Map<String, AutowireCandidateQualifier> qualifiers =
            new LinkedHashMap<String, AutowireCandidateQualifier>(0);

    private boolean nonPublicAccessAllowed = true;      //非公共连接允许

    private boolean lenientConstructorResolution = true; //宽容构造器解析,是否进行严格的控制构造器,如果不对应是否报错

    //构造器参数 construtor-arg
    private ConstructorArgumentValues constructorArgumentValues;

    //属性参数      property
    private MutablePropertyValues propertyValues;

    //方法需要重载的   lookup-method name="method" beand=""
    private MethodOverrides methodOverrides = new MethodOverrides();

    //工厂bean生成bean
    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)}
     */
    @Deprecated
    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());
            setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
            setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
            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)}
     */
    @Deprecated
    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 (StringUtils.hasLength(other.getBeanClassName())) {
            setBeanClassName(other.getBeanClassName());
        }
        if (StringUtils.hasLength(other.getFactoryBeanName())) {
            setFactoryBeanName(other.getFactoryBeanName());
        }
        if (StringUtils.hasLength(other.getFactoryMethodName())) {
            setFactoryMethodName(other.getFactoryMethodName());
        }
        if (StringUtils.hasLength(other.getScope())) {
            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());
            setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
            setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
            if (StringUtils.hasLength(otherAbd.getInitMethodName())) {
                setInitMethodName(otherAbd.getInitMethodName());
                setEnforceInitMethod(otherAbd.isEnforceInitMethod());
            }
            if (StringUtils.hasLength(otherAbd.getDestroyMethodName())) {
                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());
        setAutowireMode(defaults.getAutowireMode());
        setDependencyCheck(defaults.getDependencyCheck());
        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文件
        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 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 definitionFor this
     * reason, the default scope name is empty (empty String), with
     * singleton status being assumed until a resolved scope will be set.
     * @see #SCOPE_SINGLETON
     * @see #SCOPE_PROTOTYPE
     */
    public void setScope(String scope) {
        this.scope = scope;
        this.singleton = SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.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
     */
    @Deprecated
    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 (Constructor constructor : constructors) {
                if (constructor.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 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.
     */
    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;
    }

    /**
     * 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;
    }

    /**
     * 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 this.qualifiers.get(typeName);
    }

    /**
     * Return all registered qualifiers.
     * @return the Set of {@link AutowireCandidateQualifier} objects.
     */
    public Set<AutowireCandidateQualifier> getQualifiers() {
        return new LinkedHashSet<AutowireCandidateQualifier>(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 whether to allow access to non-public constructors and methods,
     * for the case of externalized metadata pointing to those.
     * <p>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.
     * <p>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 (<code>true</code>,
     * which is the default) or to switch to strict resolution (throwing an exception
     * in case of ambigious 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 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>&ltaop:config&gt;</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 (MethodOverride mo : methodOverrides.getOverrides()) {
                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()
     */
    @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;

        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 (this.nonPublicAccessAllowed != that.nonPublicAccessAllowed) return false;
        if (this.lenientConstructorResolution != that.lenientConstructorResolution) 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);
    }

    @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系列之二:BeanDefinition解析

《深入理解Spring系列之一:开篇》中提到在Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构,本篇将深入分析这个BeanDefinition的内部结...

spring源代码分析(3):关于BeanDefinition的思考

我们这一节重点来看看Spring的BeanDefinition的结构,我是一个刚从事软件开发工作的学生,这也只是我个人阅读源码的一些笔记和收获,如果有朋友看见了这些笔记,虚心求教,但请不要肆意攻击,指...

Spring源码阅读 --BeanDefinition

Spring是这样描述BeanDefinition的: 一个BeanDefinition描述了一个bean实例,拥有属性值,构造参数值和具体实现提供的其他信息。 这仅仅只是一个最小接口:主要的...

【Spring4揭秘 基础5】BeanDefinition及读取、注册

一、 BeanDefinition及其实现类BeanDefinition接口这个接口描述bean的结构,对应XML中的< bean >或者配置类中的@Bean 它集成了BeanMetadataEl...

Spring 实现动态注册Bean

写一个组件,需要依据配置选择DAO实现,比如JPA,Mybatis 预期效果为,系统启动时根据配置自动向spring注册相关的组件(比如JPA相关组件) 通常向spring注册组件都是使用xml...

Spring 源码之 BeanDefinition阅读

Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构

spring源码阅读(六)之BeanDefinition的载入

Spring源码阅读

Spring Boot【原理分析】(3)——BeanDefinition

一、简介BeanDefinition描述了一个Bean的实例,包括属性,构造方法参数,注解等更多信息。为后面实例化Bean提供元数据依据。 BeanDefinition的实现类有: 1. Root...
  • wwmfeng
  • wwmfeng
  • 2016年12月16日 13:24
  • 576

Spring框架之基础类—AbstractBeanDefinition抽象类

一、AbstractBeanDefinition简介AbstractBeanDefinition成熟的BeanDefinition抽象类,是具体实现类的基类。 AbstractBeanDefini...

Spring RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition

RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition均继承了AbstractBeanDefiniton,其中BeanDefiniti...
  • Truong
  • Truong
  • 2014年06月02日 08:08
  • 4233
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:spring源码学习(1) --BeanDefinition学习
举报原因:
原因补充:

(最多只允许输入30个字)