二、spring源码--BeanDefiniiton详解

BeanDefiniiton详解

spring在构造bean时,不可能像我们主动构造那样,随心所欲的new,赋值、已经完成方法调用。他需要将千差万别的class概括成为一种【统一的描述性】语言,spring提供了一个接口BeanDefintion为我们统一了这种描述bean的元数据。

bean的元数据通常是我们使用xml或者注解进行配置的数据,我们的spring容器启动之间第一步就是加载配置数据,这些元数据会被加载到内存以一个个beanDefinition的形式保存在一个map中。

一个BeanDefiniiton大概保存了以下信息:

1.定义了id、别名与Bean的对应关系(BeanDefinitionHolder)
2.具体的工厂方法(Class类型),包括工厂方法的返回类型,工厂方法的Method对象
3.构造函数、构造函数形参类型
4.Bean的class对象
5.作用范围、是否懒加载等等

以下是BeanDefiniiton的类的结构图,这里没有用类图,我觉得这里用这样的图好看一些:
在这里插入图片描述

beanDefinition来源不同可能会有不同实现,目前我们最常用的实现就是GenericBeanDefinition这个实现类。

小知识:Generic(一般的,通用的),几乎所有以这个单词打头的实现,都是spring的通用实现。

1、认识BeanDefinition

BeanDefinition接口定义了大量的常量和方法:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 常量标志一个bean的作用范围
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    // 设置父BeanDefinition,可以只对有父子关系的bean
	void setParentName(@Nullable String parentName);
	String getParentName();
    // bean的类的全限定名
	void setBeanClassName(@Nullable String beanClassName);
	String getBeanClassName();

	void setScope(@Nullable String scope);
	String getScope();

	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();

    // 设置依赖性,被依赖的bean会优先创建
	void setDependsOn(@Nullable String... dependsOn);
	String[] getDependsOn();
	// 是否允许自动装配
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();

    // 设置是否主要bean
	void setPrimary(boolean primary);
	boolean isPrimary();

	// 工厂bean和工厂方法
	void setFactoryBeanName(@Nullable String factoryBeanName);
	String getFactoryBeanName();
	void setFactoryMethodName(@Nullable String factoryMethodName);
	String getFactoryMethodName();

	ConstructorArgumentValues getConstructorArgumentValues();
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}


    // 使用setter注入时的key-value对,都保存在这里
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	// @since 5.1初始化方法和销毁方法
	void setInitMethodName(@Nullable String initMethodName);
	String getInitMethodName();
	void setDestroyMethodName(@Nullable String destroyMethodName);
	String getDestroyMethodName();

	// 为bean设置角色
	void setRole(int role);
	int getRole();

	// bean的描述
	void setDescription(@Nullable String description);
	String getDescription();

	// 返回此bean定义的可解析类型,基于bean类或其他特定元数据。
    // 这通常在运行时合并bean定义上完全解决但不一定是在配置时定义实例上。
	ResolvableType getResolvableType();
	boolean isSingleton();
	boolean isPrototype();
	boolean isAbstract();
}

2、AbstractBeanDefinition

该类对通用核心方法完成了实现(这也是抽象类的作用),同时对一些成员变量提供了默认值:

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {

	// 定义一些常量
	public static final String SCOPE_DEFAULT = "";
	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;
    // ...还有很多

	// 初始化默认值
	private volatile Object beanClass;
	private String scope = SCOPE_DEFAULT
	private boolean autowireCandidate = true;
	private boolean primary = false;
	// ...还有很多

	// 构造器
	protected AbstractBeanDefinition() {
		this(null, null);
	}

	// 指定构造器参数和属性参数
	protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs, @Nullable MutablePropertyValues pvs) {
		this.constructorArgumentValues = cargs;
		this.propertyValues = pvs;
	}

	// 使用深拷贝创建一个新的
	protected AbstractBeanDefinition(BeanDefinition original) {
		
	}


	// 复制一个bean的定义到当前bean,通常父子bean合并时可用
	public void overrideFrom(BeanDefinition other) {
		
	}

	// ...此处省略其他的方法实现
}

3、GenericBeanDefinition

该类实现比较简单,提供了设置父子关系和构建实例的方法,该类及其子类是目前版本使用最多的BeanDefinition:

public class GenericBeanDefinition extends AbstractBeanDefinition {

   @Nullable
   private String parentName;

   public GenericBeanDefinition() {
      super();
   }

   // 通过深拷贝创建一个bean
   public GenericBeanDefinition(BeanDefinition original) {
      super(original);
   }

   @Override
   public void setParentName(@Nullable String parentName) {
      this.parentName = parentName;
   }

   @Override
   @Nullable
   public String getParentName() {
      return this.parentName;
   }

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

此时,我们可以编写如下的测试用例:

@Test
public void testGenericBeanDefinition(){
    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
    beanDefinition.setBeanClassName("com.ydlclass.User");
    // 此处类似setter注入的描述
    MutablePropertyValues propertyValues = new MutablePropertyValues();
    propertyValues.addPropertyValue("name","lily");
    propertyValues.addPropertyValue("age",12);
    beanDefinition.setPropertyValues(propertyValues);
}

注:这个测试用例及其简单,但是他却可以使用字符串的形式描述一切的类。

我们再测试一种具有继承关系的bean:

public class Dog {
    private String color;
    private Integer age;
}

public class TeddyDog extends Dog{
    private String name;
}

xml可以如下定义:

<bean id="dog" class="com.ydlclass.Dog">
    <property name="color" value="white"/>
    <property name="age" value="3"/>
</bean>

<bean id="teddyDog" class="com.ydlclass.TeddyDog" parent="dog">
    <property name="name" value="小红"/>
</bean>

如果是手动定义如下:

@Test
public void testRootBeanDefinition() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    RootBeanDefinition dog = new RootBeanDefinition();
    dog.setBeanClassName("com.ydlclass.Dog");
    BeanMetadataAttribute color = new BeanMetadataAttribute("color","white");
    BeanMetadataAttribute age = new BeanMetadataAttribute("age","3");
    dog.addMetadataAttribute(color);
    dog.addMetadataAttribute(age);

    // 子Definition的创建需要依赖父Definition
    ChildBeanDefinition teddy = new ChildBeanDefinition("dog");
    teddy.setBeanClassName("com.ydlclass.TeddyDog");
    BeanMetadataAttribute name = new BeanMetadataAttribute("name","nanls");
    teddy.addMetadataAttribute(name);
}

GenericBeanDefinition在很多场景可以替换以上的内容,但是由于历史等原因,RootBeanDefinition依旧存在而且很重要,后期的归一处理还是要将不同的BeanDefinition转换或合并至一个RootBeanDefinition:

  • RootBeanDefinition与AbstractBeanDefinition是互补关系,RootBeanDefinition在AbstractBeanDefinition的基础上定义了更多属性。
  • RootBeanDefinition不能有父BeanDefinition,可以和ChildBeanDefinition配合使用构建父子关系(bean是可以继承的)。
  • 目前最常用的BeanDefinition是GenericBeanDefinition及其子类的实现,GenericBeanDefinition很强大,也可以很轻松的独立的构建父子关系。
  • 有时为了统一调用,不同的BeanDefinition可以合并、拷贝等。
// 转换的
GenericBeanDefinition definition = new GenericBeanDefinition(teddy);
// 合并的
definition.overrideFrom(dog);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值