Spring源码之IOC(二)BeanDefinition派生类

1 概述

通过前面的文章,我们对BeanDefinition接口有个深入的认识,我们知道BeanDefinition提供了bean的特性的封装,可以通过BeanDefinition对Bean的属性访问和修改,获取是否是抽象类等属性。针对更多的功能,我们就可以通过使用BeanDefinition的派生类来获取。

2 UML类图

我们来看一下BeanDefinition有哪些派生类,以及这些派生类的相互关系。

3 派生类详解

3.1 AbstractBeanDefinition

这是一个具体的,拥有基本功能实现的BeanDefinition接口的实现类。提取出来了GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition类的共有属性。包含对Spring中定义个bean的基本属性的设置和获取,例如依赖关系的检测、bean是否是单列的、自动注入方式设置等等。

那么这个抽象类具体有哪些常量和属性呢?

3.1.1 常量

(1)默认范围

public static final String SCOPE_DEFAULT = "";

这个常量表示的默认范围等价于单列模式,除非被重写。

(2)自动注入方式


public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

上面的自动注入的方式,除了最后一种不推荐使用的,一共有四种。

AUTOWIRE_NO:表示bean不支持自动注入。

AUTOWIRE_BY_NAME:表示通过名称进行自动注入。

AUTOWIRE_BY_TYPE:表示通过类型进行自动注入。

AUTOWIRE_CONSTRUCTOR:表示通过能够满足要求的适合的构造函数进行自动注入。

(3)依赖关系检测

public static final int DEPENDENCY_CHECK_NONE = 0;

public static final int DEPENDENCY_CHECK_OBJECTS = 1;

public static final int DEPENDENCY_CHECK_SIMPLE = 2;

public static final int DEPENDENCY_CHECK_ALL = 3;

在自动装配中,由于是隐式的,所以开发人员很难看出bean的每个属性是否设定完成,这个时候就需要借助依赖检测来查看bean的每个属性是否设定完成,这个就是就需要用到依赖检测模式的设定了。

DEPENDENCY_CHECK_NONE:完全不进行依赖关系检测。

DEPENDENCY_CHECK_OBJECTS:对依赖的对象进行检测。

DEPENDENCY_CHECK_SIMPLE:对依赖的基本类型进行检测,比如String、Date、Long等。

DEPENDENCY_CHECK_ALL:对全部属性进行依赖检测。

3.1.2 基本属性

    //Class对象
    @Nullable
    private volatile Object beanClass;

    //范围,这里默认位SCOPE_DEFAULT,类似于单列模式
    @Nullable
    private String scope = SCOPE_DEFAULT;

    //是否是抽象类
    private boolean abstractFlag = false;

    //是否懒加载
    private boolean lazyInit = false;

    //自动注入模式
    private int autowireMode = AUTOWIRE_NO;

    //依赖检测模式
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

    //依赖关系
    @Nullable
    private String[] dependsOn;

    //是否是自动注入候选者
    private boolean autowireCandidate = true;

    private boolean primary = false;

    //自动注入候选者与辨识标识的map
    private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);


    @Nullable
    private Supplier<?> instanceSupplier;

    //是否是公有的
    private boolean nonPublicAccessAllowed = true;

    private boolean lenientConstructorResolution = true;

    //工厂bean名称
    @Nullable
    private String factoryBeanName;

    //工厂方法名称
    @Nullable
    private String factoryMethodName;

    //构造参数对象
    @Nullable
    private ConstructorArgumentValues constructorArgumentValues;

    //属性对象
    @Nullable
    private MutablePropertyValues propertyValues;

    //重载方法对象
    @Nullable
    private MethodOverrides methodOverrides;

    //初始化函数名称
    @Nullable
    private String initMethodName;

    //销毁函数名称
    @Nullable
    private String destroyMethodName;

    private boolean enforceInitMethod = true;

    private boolean enforceDestroyMethod = true;

    private boolean synthetic = false;

    //bean的角色
    private int role = BeanDefinition.ROLE_APPLICATION;

    @Nullable
    private String description;

    @Nullable
    private Resource resource;

上面的属性部分给出了注释,针对没有给注释的,目前我也不知道具体的用处,后面再进一步完善。

3.1.3 函数

针对函数的分析,我们这里就直接将构造函数和普通函数放在一起说明了。

针对比较简单的构造函数我们就不拿出来分析了,现在直接看一下通过深复制来实现的一个构造函数。

protected AbstractBeanDefinition(BeanDefinition original) {
		setParentName(original.getParentName());
		setBeanClassName(original.getBeanClassName());
		setScope(original.getScope());
		setAbstract(original.isAbstract());
		setLazyInit(original.isLazyInit());
		setFactoryBeanName(original.getFactoryBeanName());
		setFactoryMethodName(original.getFactoryMethodName());
		setRole(original.getRole());
		setSource(original.getSource());
		copyAttributesFrom(original);

		if (original instanceof AbstractBeanDefinition) {
			AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original;
			if (originalAbd.hasBeanClass()) {
				setBeanClass(originalAbd.getBeanClass());
			}
			if (originalAbd.hasConstructorArgumentValues()) {
				setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
			}
			if (originalAbd.hasPropertyValues()) {
				setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
			}
			if (originalAbd.hasMethodOverrides()) {
				setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
			}
			setAutowireMode(originalAbd.getAutowireMode());
			setDependencyCheck(originalAbd.getDependencyCheck());
			setDependsOn(originalAbd.getDependsOn());
			setAutowireCandidate(originalAbd.isAutowireCandidate());
			setPrimary(originalAbd.isPrimary());
			copyQualifiersFrom(originalAbd);
			setInstanceSupplier(originalAbd.getInstanceSupplier());
			setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
			setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
			setInitMethodName(originalAbd.getInitMethodName());
			setEnforceInitMethod(originalAbd.isEnforceInitMethod());
			setDestroyMethodName(originalAbd.getDestroyMethodName());
			setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
			setSynthetic(originalAbd.isSynthetic());
			setResource(originalAbd.getResource());
		}
		else {
			setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
			setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
			setResourceDescription(original.getResourceDescription());
		}
	}

上面这个函数做的其实就是复制参数BeanDefinition的属性来构建新的BeanDefinition。

其余的函数其实就是属性的修改器和访问器,这里就不进一步说明了。

3.2 AnnotatedBeanDefinition

这个接口的作用是在类没有被加载的情况下,暴露出bean所属类的AnnotationMetadata。AnnotationMetadata类提供了在类没有被加载的情况下,对类属性的访问的函数。

这个接口提供了两个函数。

/**
 * 获取类注释元数据对象
 */
AnnotationMetadata getMetadata();

/**
 * 获取工厂方法的元数据对象
 */
@Nullable
MethodMetadata getFactoryMethodMetadata();

3.3 ChildBeanDefinition

这个BeanDefinition的设置继承于父类,并且对父类有一个固定的依赖关系。当然这里面继承的属性就包括了构造函数参数、属性和方法重写等属性。从Spring 2.5开始,在大多数情况下,GenericBeanDefinition有效地取代了ChildBeanDefinition。

这个类仅仅有一个属性:parentName,来表明它的继承关系。它的构造函数就比较简单了,其实就是使用String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs,这四个参数来初始化。

3.4 GenericBeanDefinition

GenericBeanDefinition提供了一站式的标准的BeanDefinition功能,像其他的BeanDefinition一样,它允许实例化一个类的BeanDefinition并且设置构造函数参数和属性。可以通过设置parentName来和基类的配置建立固定的依赖关系。

通常情况下我们使用GenericBeanDefinition,但是当派生关系预先确定了,就使用RootBeanDefinition/ChildBeanDefinition。

属性和构造函数都比较简单,这里就不进行任何说明了。

3.5 RootBeanDefinition

RootBeanDefinition代表了复合的BeanDefinition,它可能被创建通过相会继承的原始的BeanDefinition。通常情况下我们使用GenericBeanDefinition,而不是RootBeanDefinition。因为GenericBeanDefinition可以动态指定继承关系。

3.5.1 属性

这里我们直接在源码中加入注释来说明属性作用。

//对BeanDefinition的封装,里面包含了BeanDefinition和bean名称以及别名
@Nullable
private BeanDefinitionHolder decoratedDefinition;

//提供了对注释的访问入口
@Nullable
private AnnotatedElement qualifiedElement;

boolean allowCaching = true;

boolean isFactoryMethodUnique = false;

//封装了Java反射类型,提供了到达类型的入口。
@Nullable
volatile ResolvableType targetType;

//缓存BeanDefinition确定的class对象
@Nullable
volatile Class<?> resolvedTargetType;

//缓存工厂方法返回的类的ResolvableType对象
@Nullable
volatile ResolvableType factoryMethodReturnType;

//构造器参数锁,这个锁主要用于下面四个属性
final Object constructorArgumentLock = new Object();

//缓存已知的构造器和工厂方法
@Nullable
Executable resolvedConstructorOrFactoryMethod;

//标识构造器参数是否已经解决
boolean constructorArgumentsResolved = false;

//缓存所有已经解决的构造器参数
@Nullable
Object[] resolvedConstructorArguments;

//缓存部分准备好的构造器参数
@Nullable
Object[] preparedConstructorArguments;

//用于下面两个后处理属性的锁
final Object postProcessingLock = new Object();

boolean postProcessed = false;

@Nullable
volatile Boolean beforeInstantiationResolved;

@Nullable
private Set<Member> externallyManagedConfigMembers;

@Nullable
private Set<String> externallyManagedInitMethods;

@Nullable
private Set<String> externallyManagedDestroyMethods;

上面的部分属性从名字就可以知道用处,所以没有一一说明。如有不同观点,欢迎指正。

3.5.2 函数

针对函数部分,我们就不进行一一说明了,这里仅仅挑选一些来分析,因为大部分都是属性的修改器和访问器。

这里,我们首先挑选一个构造函数来看一下吧:

public RootBeanDefinition(@Nullable Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
		super();
		setBeanClass(beanClass);
		setAutowireMode(autowireMode);
		if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
			setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
		}
	}

上面的函数其实就是传入了bean的类型的Class对象、自动注入模式、依赖检测模式来初始化RootBeanDefinition对象。

我们再来看一下克隆BeanDefinition对象是怎样实现的:

@Override
public RootBeanDefinition cloneBeanDefinition() {
    return new RootBeanDefinition(this);
}

其实就是调用构造器来进行初始化,并返回结果。

4 AnnotatedGenericBeanDefinition

这个BeanDefinition继承了GenericBeanDefinition,并通过实现AnnotatedBeanDefinition来添加对注释元数据的获取途径。

4.1 属性

从这个类的继承关系我们就可以猜想她肯定含有注释元数据属性和方法元数据属性。

private final AnnotationMetadata metadata;

@Nullable
private MethodMetadata factoryMethodMetadata;

这两个属性完成了对类的注释和方法属性的封装。

其余的一些构造函数和属性的访问器、修改器我们就不一一说明了。

上面就是对BeanDefinition的派生类的分析,后面将继续分析参与到IOC的工具类的源码,欢迎交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值