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的使用主要作用在:
- 我们在通过XML的方式对Spring中的Bean进行配置时,不管Bean中的属性是何种类型,都是直接通过字面值来设置Bean中的属性。那么是什么在这其中做转换呢?这里用到的就是PropertyEditor。
- 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的一个重要实现并且提供了嵌套属性访问的功能。关于嵌套属性的访问可以参考这篇博客: