Back
Featured image of post Spring源码IOC篇-BeanDefinition和BeanWrapper

Spring源码IOC篇-BeanDefinition和BeanWrapper

1、BeanDefinition简介

​ BeanDefinition 是用来描述 Bean 的,里面存放着关于 Bean 的一系列信息,比如 Bean 的作用域,Bean 所对应的 class, 是否懒加载,是否 Primary 等等。有了它 Spring 容器就掌握了实例化 bean 所需要的一些重要信息,Spring 才可以对其进行实例化。

​ BeanDefinition 有如下的基础属性:

属性名称 介绍
parentName 双亲bean定义(parent bean definition)的名称.如果没有双亲bean定义,这里为空
beanClassName bean的类名,在bean factory的post process阶段可能会被修改。注意该属性并不总是运行时被对应bean真正使用的类的名称:比如,bean是通过某个类的静态工厂方法生成的,这里是该类的类名,再比如,bean是通过一个工厂bean生成的,那这里为空。
scope 作用域, singleton或者prototype。在bean的作用域尚未决定之前,该属性为null
lazyInit 是否懒加载,仅适用于singleton bean。当一个singleton bean被指定lazyInit为false时,它会在bean factory启动时执行singleton bean初始化的阶段被实例化。
dependsOn 所依赖的bean的名称,如果有多个依赖的bean,这里需要都列出来。容器会保证这些被依赖的bean先被初始化。
autowireCandidate 该bean是否作为自动绑定的候选,仅适用于基于类型的自动绑定。基于名称的绑定不受此属性影响。
primary 当前bean定义是否主bean。当某个自动绑定遇到多个候选bean时,primary属性为true的会被使用。
factoryBeanName 如果要使用factory bean来创建bean,这里指定了相应的工厂bean的类名称
factoryMethodName 工厂方法名称。基于类静态工厂方法的情况下,结合beanClassName使用;基于工厂bean的情况下,结合factoryBeanName使用。如果bean定义的constructorArgumentValues有内容,工厂方法被调用时会使用该属性。
constructorArgumentValues bean创建时的构造函数参数
propertyValues 新建的bean需要设置的属性值
initMethodName bean的初始化方法
destroyMethodName bean的销毁方法
role bean的角色:APPLICATION,SUPPORT,INFRASTRUCTURE。提示框架该bean的角色和重要程度。
description bean的描述,human readable
singleton 作用域断言,是否singleton
prototype 作用域断言,是否prototype
abstract 是否抽象bean定义,抽象bean定义的目的不是用于实例化bean,而是有其他目的。
resourceDescription 资源描述文本,告知当前bean定义的来源,一般用于错误时显示上下文。
originatingBeanDefinition 返回来源bean定义(如果有的话)。通过该属性,可以获取被修饰的bean定义。需要注意的是该属性仅仅返回直接来源bean定义而不是返回最深处的来源bean定义。一个bean定义的originatingBeanDefinition属性隐含了一个来源bean定义链,通过迭代访问该链,可以最终找到最终来自用户的bean定义。

除了上述直接通过BeanDefinition自身进行的定义,接口BeanDefinition还继承了另外两个接口 : AttributeAccessor和BeanMetadataElement。

AttributeAccessor接口定义了对一个bean属性的访问 :

方法 介绍
setAttribute 设置指定的属性为特定值
getAttribute 获取指定的属性的值
removeAttribute 删除指定的属性
hasAttribute 是否拥有指定的属性
attributeNames 获取所有属性的名称

2、BeanDefinition的实现

  • AbstractBeanDefinition

AbstractBeanDefinition中并没有太复杂的实现逻辑,而是主要是用于:

AbstractBeanDefinition是最终全功能BeanDefinition实现类的基类,也就是这些类的共同属性和公共逻辑实现。

  • 定义共用的构造函数。
  • 定义共用BeanDefinition属性以及提供它们的getter/setter方法。
  • 其他一些共用工具方法 : 从另外一个bean定义覆盖当前bean定义,应用初始值等等。

另外AbstractBeanDefinition继承自BeanMetadataAttributeAccessor。BeanMetadataAttributeAccessor为AbstractBeanDefinition提供了接口AttributeAccessor定义的属性访问能力以及BeanMetadataElement定义的源配置对象设置/获取能力。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {

	/**
	 * Constant for the default scope name: {@code ""}, equivalent to singleton
	 * status unless overridden from a parent bean definition (if applicable).
	 */
	public static final String SCOPE_DEFAULT = "";

	/**
	 * Constant that indicates no external 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
	 * {@link #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.
	 * <p>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;

	//是否懒加载
	@Nullable
	private Boolean lazyInit;

	// 自动装配模式 : 初始化为不要使用自动装配
	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;

	//MethodOverrides配置
	private MethodOverrides methodOverrides = new 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;

	@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;
	}

	/**
	 * Create a new AbstractBeanDefinition as a 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());
		setScope(original.getScope());
		setAbstract(original.isAbstract());
		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()));
			}
			Boolean lazyInit = originalAbd.getLazyInit();
			if (lazyInit != null) {
				setLazyInit(lazyInit);
			}
			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()));
			setLazyInit(original.isLazyInit());
			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).
	 * <ul>
	 * <li>Will override beanClass if specified in the given bean definition.
	 * <li>Will always take {@code abstract}, {@code scope},
	 * {@code lazyInit}, {@code autowireMode}, {@code dependencyCheck},
	 * and {@code dependsOn} from the given bean definition.
	 * <li>Will add {@code constructorArgumentValues}, {@code propertyValues},
	 * {@code methodOverrides} from the given bean definition to existing ones.
	 * <li>Will override {@code factoryBeanName}, {@code factoryMethodName},
	 * {@code initMethodName}, and {@code destroyMethodName} if specified
	 * in the given bean definition.
	 * </ul>
	 *
	 * 本方法的一个主要用途是用在根据bean定义之间的父子关系生成最终merged的孩子bean定义对象:
	 * 此时先使用双亲bean定义生成一个RootBeanDefinition,然后调用该RootBeanDefinition
	 * 对象的overrideFrom(other)方法,这里other就是child bean定义,然后这个RootBeanDefinition
	 * 就是一个继承自双亲bean定义又符合原始child bean定义的一个最终被使用的BeanDefinition了。
	 *
	 *
	 *
	 */
	public void overrideFrom(BeanDefinition other) {
		if (StringUtils.hasLength(other.getBeanClassName())) {
			setBeanClassName(other.getBeanClassName());
		}
		if (StringUtils.hasLength(other.getScope())) {
			setScope(other.getScope());
		}
		setAbstract(other.isAbstract());
		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());
			}
			Boolean lazyInit = otherAbd.getLazyInit();
			if (lazyInit != null) {
				setLazyInit(lazyInit);
			}
			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());
			setLazyInit(other.isLazyInit());
			setResourceDescription(other.getResourceDescription());
		}
	}

	/**
	 * Apply the provided default values to this bean.
	 * @param defaults the default settings to apply
	 * @since 2.5
	 */
	public void applyDefaults(BeanDefinitionDefaults defaults) {
		Boolean lazyInit = defaults.getLazyInit();
		if (lazyInit != null) {
			setLazyInit(lazyInit);
		}
		setAutowireMode(defaults.getAutowireMode());
		setDependencyCheck(defaults.getDependencyCheck());
		setInitMethodName(defaults.getInitMethodName());
		setEnforceInitMethod(false);
		setDestroyMethodName(defaults.getDestroyMethodName());
		setEnforceDestroyMethod(false);
	}

...

}

继承自AbstractBeanDefinition的全功能BeanDefinition实现类有 :

  • RootBeanDefinition

RootBeanDefinition继承自 AbstractBeanDefinition,它可以单独作为一个 BeanDefinition,也可以作为其他 BeanDefinition 的父类。RootBeanDefinition 在 AbstractBeanDefinition 的基础上定义了更多属性。

public class RootBeanDefinition extends AbstractBeanDefinition {

	@Nullable
	// BeanDefinitionHolder 存储 Bean 的名称、别名、BeanDefinition
	private BeanDefinitionHolder decoratedDefinition;

	@Nullable
	// AnnotatedElement 是java反射包的接口,通过它可以查看 Bean 的注解信息
	private AnnotatedElement qualifiedElement;

	/** Determines if the definition needs to be re-merged. */
	//确定是否需要重新合并定义
	volatile boolean stale;
	// 允许缓存
	boolean allowCaching = true;
	// 工厂方法是否唯一
	boolean isFactoryMethodUnique = false;

	@Nullable
	// 封装了 java.lang.reflect.Type,提供了泛型相关的操作
	volatile ResolvableType targetType;

	/** Package-visible field for caching the determined Class of a given bean definition. */
	@Nullable
	// 缓存 Class,表示 RootBeanDefinition 存储哪个类的信息
	volatile Class<?> resolvedTargetType;

	/** Package-visible field for caching if the bean is a factory bean. */
	@Nullable
	//是否是FactoryBean
	volatile Boolean isFactoryBean;

	/** Package-visible field for caching the return type of a generically typed factory method. */
	@Nullable
	// 缓存工厂方法的返回类型
	volatile ResolvableType factoryMethodReturnType;

	/** Package-visible field for caching a unique factory method candidate for introspection. */
	@Nullable
	//缓存候选的工厂方法
	volatile Method factoryMethodToIntrospect;

	/** Common lock for the four constructor fields below. */
	// 这是以下四个构造方法字段的通用锁
	final Object constructorArgumentLock = new Object();

	/** Package-visible field for caching the resolved constructor or factory method. */
	@Nullable
	// 用于缓存已解析的构造方法或工厂方法
	Executable resolvedConstructorOrFactoryMethod;

	/** Package-visible field that marks the constructor arguments as resolved. */
	//将构造方法标注为已解析
	boolean constructorArgumentsResolved = false;

	/** Package-visible field for caching fully resolved constructor arguments. */
	@Nullable
	// 用于缓存完全解析的构造方法参数
	Object[] resolvedConstructorArguments;

	/** Package-visible field for caching partly prepared constructor arguments. */
	@Nullable
	//缓存等待解析的构造方法参数
	Object[] preparedConstructorArguments;

	/** Common lock for the two post-processing fields below. */
	// 这是以下两个后处理字段的通用锁
	final Object postProcessingLock = new Object();

	/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied. */
	// 表明是否被 MergedBeanDefinitionPostProcessor 处理过
	boolean postProcessed = false;

	/** Package-visible field that indicates a before-instantiation post-processor having kicked in. */
	@Nullable
	// 在生成代理的时候会使用,表明是否已经生成代理
	volatile Boolean beforeInstantiationResolved;

	@Nullable
	// 实际缓存的类型是 Constructor、Field、Method 类型
	private Set<Member> externallyManagedConfigMembers;

	@Nullable
	// InitializingBean中 的 init 回调函数名 afterPropertiesSet 会在这里记录,以便进行生命周期回调
	private Set<String> externallyManagedInitMethods;

	@Nullable
	// DisposableBean 的 destroy 回调函数名 destroy 会在这里记录,以便进生命周期回调
	private Set<String> externallyManagedDestroyMethods;
    ...
}
  • ChildBeanDefinition

ChildBeanDefinition很适合父子bean定义关系明确的情况下基于双亲bean定义和自身少量设置一些个性化属性从而进行子bean定义。

实际上,真正在创建子bean定义规定的bean对象时,Spring框架内部是将双亲bean定义和孩子bean定义合并形成一个最终使用的RootBeanDefinition,这里孩子bean定义中设置的属性会被优先使用,没有指定的都会继承使用双亲bean定义中的设置。

  • GenericBeanDefinition

GenericBeanDefinition 是 Spring 2.5 以后新引入的 BeanDefinition,是 ChildBeanDefinition 更好的替代者,它同样可以通过 setParentName 方法设置父 BeanDefinition。

3、BeanDefinition的整合

过上面可以看到BeanDefinition存在着父子结构的关系,并且在最终使用时会统一整合成RootBeanDefinition,下面我们来看一下BeanDefinition是如何整合的。

下面是获取Bean实例时的伪代码,会有getMergedLocalBeanDefinition(beanName)这样一个步骤:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	// ...
	// 这里根据bean名称获取MergedBeanDefinition,结果类型是RootBeanDefinition 
	final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
	// ...		
	createBean(beanName, mbd, args);
	
	// ...
}

从上面代码可见,通过方法getMergedLocalBeanDefinition(),一个RootBeanDefinition mbd根据bean名称生成了。我们进而跟踪getMergedLocalBeanDefinition()的实现。如下 :

/**
	 * Return a merged RootBeanDefinition, traversing the parent bean definition
	 * if the specified bean corresponds to a child bean definition.
	 * @param beanName the name of the bean to retrieve the merged definition for
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) 
	throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

	/**
	 * Return a RootBeanDefinition for the given top-level bean, by merging with
	 * the parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */	
	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {

		return getMergedBeanDefinition(beanName, bd, null);
	}

	/**
	 * Return a RootBeanDefinition for the given bean, by merging with the
	 * parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @param containingBd the containing bean definition in case of inner bean,
	 * or null in case of a top-level bean
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */		
	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			// 准备一个RootBeanDefinition变量引用,用于记录要构建和最终要返回的BeanDefinition,
			// 这里根据上下文不难猜测 mbd 应该就是 mergedBeanDefinition 的缩写。
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
				if (bd.getParentName() == null) {
					// bd不是一个ChildBeanDefinition的情况,换句话讲,这 bd应该是 :
					// 1. 一个独立的 GenericBeanDefinition 实例,parentName 属性为null
					// 2. 或者是一个 RootBeanDefinition 实例,parentName 属性为null
					// 此时mbd直接使用一个bd的复制品
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {						
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// bd是一个ChildBeanDefinition的情况,
					// 这种情况下,需要将bd和其parent bean definition 合并到一起,
					// 形成最终的 mbd
					// 下面是获取bd的 parent bean definition 的过程,最终结果记录到 pbd,
					// 并且可以看到该过程中递归使用了getMergedBeanDefinition(), 为什么呢?
					// 因为 bd 的 parent bd 可能也是个ChildBeanDefinition,所以该过程
					// 需要递归处理
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) 
									parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + 
										"' is equal to bean name '" + beanName +
							"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(
							bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + 
								bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					// 现在已经获取 bd 的parent bd到pbd,从上面的过程可以看出,这个pbd
					// 也是已经"合并"过的。
					// 这里根据pbd创建最终的mbd,然后再使用bd覆盖一次,
					// 这样就相当于mbd来自两个BeanDefinition:
					// 当前 BeanDefinition 及其合并的("Merged")双亲 BeanDefinition,
					// 然后mbd就是针对当前bd的一个MergedBeanDefinition(合并的BeanDefinition)了。
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original 
				// inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}

从上面的MergedBeanDefinition的获取过程可以看出,一个MergedBeanDefinition其实就是一个"合并了的BeanDefinition",最终以RootBeanDefinition的类型存在。

4、BeanWrapper简介

​ BeanWrapper 是 Spring 的低级 JavaBeans 基础结构的中央接口, 相当于一个代理器, 提供用于分析和操作标准 JavaBean 的操作:获得和设置属性值(单独或批量),获取属性描述符以及查询属性的可读性/可写性的能力。BeanWrapper 大部分情况下是在 Spring IoC 内部进行使用,通过 BeanWrapper,Spring IoC 容器可以用统一的方式来访问 bean 的属性。用户很少需要直接使用 BeanWrapper 进行编程。

public interface BeanWrapper extends ConfigurablePropertyAccessor {

	/**
	 * Specify a limit for array and collection auto-growing.
	 * <p>Default is unlimited on a plain BeanWrapper.
	 * @since 4.1
	 */
    //指定数组和集合自动增长的限制。
	void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);

	/**
	 * Return the limit for array and collection auto-growing.
	 * @since 4.1
	 */
     //返回数组和集合自动增长的限制。
	int getAutoGrowCollectionLimit();

	/**
	 * Return the bean instance wrapped by this object.
	 */
    //返回由该对象包装的bean实例。
	Object getWrappedInstance();

	/**
	 * Return the type of the wrapped bean instance.
	 */
    // 获取包装的Bean的class
	Class<?> getWrappedClass();

	/**
	 * Obtain the PropertyDescriptors for the wrapped object
	 * (as determined by standard JavaBeans introspection).
	 * @return the PropertyDescriptors for the wrapped object
	 */
    // 获取所有属性的属性描述符
	PropertyDescriptor[] getPropertyDescriptors();

	/**
	 * Obtain the property descriptor for a specific property
	 * of the wrapped object.
	 * @param propertyName the property to obtain the descriptor for
	 * (may be a nested path, but no indexed/mapped property)
	 * @return the property descriptor for the specified property
	 * @throws InvalidPropertyException if there is no such property
	 */
     // 获取指定属性的属性描述符
	PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;

}

这里需要先了解一个概念,什么是属性描述符?

PropertyDescriptor:属性描述符,能够描述javaBean中的属性,通过属性描述符我们能知道这个属性的类型,获取到操纵属性的方法(getter/setter)

这里实际上是依托于java的内省机制

内省(Introspector)是Java语言对Bean类属性、事件的一种缺省处理方法。

例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。

通过getName/setName来访问name属性,这就是默认的规则。

Java中提供了一套API用来访问某个属性的getter/setter方法,通过这些API可以使你不需要了解这个规则,

这些API存放于包java.beans中。

如何使用内省机制:

一般的做法是通过类Introspector来获取某个对象的BeanInfo信息。

然后通过BeanInfo来获取属性的描述器(PropertyDescriptor)。

通过这个属性描述器就可以获取某个属性对应的getter/setter方法。

然后我们就可以通过反射机制来调用这些方法。

内省和反射的区别:

反射可以操作各种类的属性,而内省只是通过反射来操作JavaBean的属性

内省设置属性值肯定会调用setter方法,反射可以不用(反射可直接操作属性Field)

反射就像照镜子,然后能看到.class的所有,是客观的事实。内省更像主观的判断:比如看到getName(),内省就会认为这个类中有name字段,但事实上并不一定会有name;通过内省可以获取bean的getter/setter

省机制的示例:

public class Point {
	private Integer x;
	private Integer y;

	public Point() {
	}

	public Point(Integer x, Integer y) {
		this.x = x;
		this.y = y;
	}

	public Integer getX() {
		return x;
	}

	public void setX(Integer x) {
		this.x = x;
	}

	public Integer getY() {
		return y;
	}

	public void setY(Integer y) {
		this.y = y;
	}
}
//用于演示java内省机制、
public class ReflectTest {
	public static void main(String[] args) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
		Point point = new Point(2, 5);
		String proName = "x";
		getProperty(point, proName);
		setProperty(point, proName);
		allProperty(point);
	}

	private static void setProperty(Point point, String proName) throws InvocationTargetException, IllegalAccessException, IntrospectionException {
		PropertyDescriptor proDescriptor = new PropertyDescriptor(proName, Point.class);
		        Method methodSetX = proDescriptor.getWriteMethod();
		        methodSetX.invoke(point, 8);
		        System.out.println(point.getX());// 8
	}

	private static void getProperty(Point point, String proName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
		PropertyDescriptor proDescriptor = new PropertyDescriptor(proName, Point.class);
		        Method methodGetX = proDescriptor.getReadMethod();
		        Object objx = methodGetX.invoke(point);
		System.out.println(objx);
	}

	private static void allProperty(Point point) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
		BeanInfo beanInfo = Introspector.getBeanInfo(Point.class);
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			Method readMethod = propertyDescriptor.getReadMethod();
			Object invoke = readMethod.invoke(point);
			System.out.println(invoke);
		}
	}
}

5、BeanWrapperImpl

beanWrapperImpl是BeanWrapper的唯一实现。

这里我们主要看下BeanWrapper继承的PropertyAccessor、TypeConverter、PropertyEditorRegistry接口。

  • PropertyEditorRegistry
// 这个接口的功能很简单,就是用来注入属性编辑器(PropertyEditor),那么什么是PropertyEditor呢?
public interface PropertyEditorRegistry {

 void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);

 void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor);

 @Nullable
 PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath);

}

PropertyEditor是JavaBean规范定义的接口,这是java.beans中一个接口,其设计的意图是图形化编程上,方便对象与String之间的转换工作,而Spring将其扩展,方便各种对象与String之间的转换工作。Spring中对PropertyEditor的使用主要作用在:

  1. 我们在通过XML的方式对Spring中的Bean进行配置时,不管Bean中的属性是何种类型,都是直接通过字面值来设置Bean中的属性。那么是什么在这其中做转换呢?这里用到的就是PropertyEditor。
  2. SpringMVC在解析请求参数时,也是使用的PropertyEditor。
  • TypeConverter
// 定义了进行类型转换时的一些规范,就像名字定义的那样,主要用来做类型转换
public interface TypeConverter {
 
    // 将指定的值转换成指定的类型
 @Nullable
 <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException;

    // 相对于上面这个方法下面这个三种方法能处理转换过程中的泛型
 @Nullable
 <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
   @Nullable MethodParameter methodParam) throws TypeMismatchException;
 @Nullable
 <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
   throws TypeMismatchException;
 default <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
   @Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {

  throw new UnsupportedOperationException("TypeDescriptor resolution not supported");
 }

}

在BeanWrapperImpl中主要通过类型转换的委托类TypeConverterDelegate进行类型转换。Spring有两种自动类型转换器,一种是Converter,另一种是上面提到过的PropertyEditor。在TypeConverterDelegate中会先使用PropertyEditor转换器器转换,如果没找到对应的转换器器,会⽤ConversionService来进行对象转换。

class TypeConverterDelegate {

 private final PropertyEditorRegistrySupport propertyEditorRegistry;

 @Nullable
 private final Object targetObject;

 public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
   @Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {

  // 查看是否为当前这个类型配置了定制的PropertyEditor
  PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

  ConversionFailedException conversionAttemptEx = null;

  // 获取当前容器中的类型转换业务类
  ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
        
        // 在这里可以看出,Spring底层在进行类型转换时有两套机制
        // 1.首选的是采用PropertyEditor
        // 2.在没有配置PropertyEditor的情况下,会采用conversionService
  if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
   TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
   if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
    try {
                    // 通过conversionService进行类型转换
     return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
    }
    catch (ConversionFailedException ex) {
     // fallback to default conversion logic below
     conversionAttemptEx = ex;
    }
   }
  }

  Object convertedValue = newValue;

  // 配置了定制的属性编辑器,采用PropertyEditor进行属性转换
  if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
   if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
     convertedValue instanceof String) {
    TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
    if (elementTypeDesc != null) {
     Class<?> elementType = elementTypeDesc.getType();
     if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
      convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
     }
    }
   }
   if (editor == null) {
                // 没有配置定制的属性编辑器,采用默认的属性编辑器
    editor = findDefaultEditor(requiredType);
   }
            // 采用属性编辑器进行转换,需要注意的是,默认情况下PropertyEditor只会对String类型的值进行类型转换
   convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
  }
        // .....
  return (T) convertedValue;
 }
 
}

有关两者之间的对比可以参考这篇博客:

https://blog.csdn.net/f641385712/article/details/90702928

  • PropertyAccessor
public interface PropertyAccessor {
 
    // 嵌套属性的分隔符,比如"foo.bar"将会调用getFoo().getBar()两个方法
 String NESTED_PROPERTY_SEPARATOR = ".";
 char NESTED_PROPERTY_SEPARATOR_CHAR = '.';

   // 代表角标index的符号  如person.addresses[0]  这样就可以把值放进集合/数组/Map里了
 String PROPERTY_KEY_PREFIX = "[";
 char PROPERTY_KEY_PREFIX_CHAR = '[';
 String PROPERTY_KEY_SUFFIX = "]";
 char PROPERTY_KEY_SUFFIX_CHAR = ']';

    // 该属性是否可读/可写,不存在则返回false
 boolean isReadableProperty(String propertyName);
 boolean isWritableProperty(String propertyName);
 
    // 获取/设置属性的方法,基本见名知意
 @Nullable
 Class<?> getPropertyType(String propertyName) throws BeansException;
 @Nullable
 TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
 @Nullable
 Object getPropertyValue(String propertyName) throws BeansException;
 void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
 void setPropertyValue(PropertyValue pv) throws BeansException;
 void setPropertyValues(Map<?, ?> map) throws BeansException;
 void setPropertyValues(PropertyValues pvs) throws BeansException;
 void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown)
   throws BeansException;
 void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
   throws BeansException;

}

属性访问器PropertyAccessor接口的作用是存/取Bean对象的属性。所有Spring创建的Bean对象都使用该接口存取Bean属性值。通过BeanWrapperImpl的类图中我们可以发现BeanWrapperImpl继承了AbstractNestablePropertyAccessor类。这个类是PropertyAccessor的一个重要实现并且提供了嵌套属性访问的功能。关于嵌套属性的访问可以参考这篇博客:

https://www.cnblogs.com/binarylei/p/10267928.html