Spring - 理解BeanDefinition

BeanDefinition

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

不管是是通过xml配置文件的<Bean>标签,还是通过注解配置的@Bean,它最终都会被解析成一个Bean定义信息对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。

从上可知BeanDefinition这个接口对Spring IoC容器的重要之处,所以了解好了它(以及子类),能让我们更大视野的来看Spring管理Bean的一个过程,也能透过现象看本质。

比喻

  1. Spring IoC容器好比一间餐馆
    当你来到餐馆,通常会直接招呼服务员:点菜!至于菜的原料是什么?如何用原料把菜做出来?可能你根本就不关心。IoC容器也是一样,你只需要告诉它需要某个bean,它就把对应的实例(instance)扔给你,至于这个bean是否依赖其他组件,怎样完成它的初始化,根本就不需要你关心。
  2. BeanDefinition就是做菜的原料
    容器中的每一个bean都会有一个对应的BeanDefinition实例,该实例负责保存bean对象的 所有 必要信息,包括bean对象的beanClass、scope、lazyInit类属性、是否是抽象类、构造方法和参数、其它属性等等(所以BeanDefinition就好比做菜的原料)
  3. BeanDefinitionRegistry和 BeanFactory就是菜谱
    BeanDefinitionRegistry抽象出bean的注册逻辑,而BeanFactory则抽象出了bean的管理逻辑。 各个BeanFactory的实现类就具体承担了bean的注册以及管理工作。

在这里插入图片描述

BeanDefinition源码

源码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 单例Bean还是原型Bean
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	
	// Bean角色
	int ROLE_APPLICATION = 0; //应用程序重要组成部分
	int ROLE_SUPPORT = 1; //做为大量配置的一部分(支持、扩展类)  实际上就是说,我这个Bean是用户的,是从配置文件中过来的。
	int ROLE_INFRASTRUCTURE = 2; //指内部工作的基础构造  实际上是说我这Bean是Spring自己的,和你用户没有一毛钱关系
	
	// Modifiable attributes
	//parent definition(若存在父类的话,就设置进去)
	void setParentName(@Nullable String parentName);
	@Nullable
	String getParentName();
	
	// 指定Class类型。需要注意的是该类型还有可能被改变在Bean post-processing阶段
	// 若是getFactoryBeanName  getFactoryMethodName这种情况下会改变
	void setBeanClassName(@Nullable String beanClassName);
	@Nullable
	String getBeanClassName();

	//SCOPE_SINGLETON或者SCOPE_PROTOTYPE两种
	void setScope(@Nullable String scope);
	@Nullable
	String getScope();

	// @Lazy 是否需要懒加载(默认都是立马加载的)
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();
	
	// 此Bean定义需要依赖的Bean(显然可以有多个)
	void setDependsOn(@Nullable String... dependsOn);
	@Nullable
	String[] getDependsOn();
	
	// 这个Bean是否允许被自动注入到别的地方去(默认都是被允许的)
	// 注意:此标志只影响按类型装配,不影响byName的注入方式的~~~~
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();

	// 是否是首选的  @Primary
	void setPrimary(boolean primary);
	boolean isPrimary();
	
	// 指定使用的工厂Bean(若存在)的名称~
	void setFactoryBeanName(@Nullable String factoryBeanName);
	@Nullable
	String getFactoryBeanName();
	//指定工厂方法~
	void setFactoryMethodName(@Nullable String factoryMethodName);
	@Nullable
	String getFactoryMethodName();
	
	// 获取此Bean的构造函数参数值们  ConstructorArgumentValues:持有构造函数们的 
	// 绝大多数情况下是空对象 new ConstructorArgumentValues出来的一个对象
	// 当我们Scan实例化Bean的时候,可能用到它的非空构造,这里就会有对应的值了,然后后面就会再依赖注入了
	ConstructorArgumentValues getConstructorArgumentValues();
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	// 获取普通属性集合~~~~
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	// Read-only attributes
	boolean isSingleton();
	boolean isPrototype();
	boolean isAbstract();
	
	// 对应上面的role的值
	int getRole();
	//@Description
	@Nullable
	String getDescription();
	// 返回该Bean定义来自于的资源的描述(用于在出现错误时显示上下文)
	@Nullable
	String getResourceDescription();
	//返回原始BeanDefinition,如果没有则返回@null
	// 若这个Bean定义被代理、修饰过  这个方法可以返回原始的
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();
}

具体实现类

  1. AbstractBeanDefinition
    AbstractBeanDefinition实现了BeanDefinition定义的一系列操作,定义了描述Bean画像的一系列属性,在AbstractBeanDefinition的基础上,Spring衍生出了一系列具有特殊用途的BeanDefinition。

  2. GenericBeanDefinition
    标准通用的beanDefinition。除了具有指定类、可选的构造参数值和属性参数这些其它beanDefinition一样的特性外,它还具有通过parenetName属性来动态设置parent bean definition。

  3. ChildBeanDefinition
    子Bean定义信息,依赖于父类RootBeanDefinition
    ChildBeanDefinition是一种bean definition,它可以继承它父类的设置,即ChildBeanDefinition对RootBeanDefinition有一定的依赖关系。

  4. RootBeanDefinition
    一个RootBeanDefinition定义表明它是一个可合并的beanDefinition:即在spring beanFactory运行期间,可以返回一个特定的bean。但在Spring2.5以后,我们绝大多数情况还是可以使用GenericBeanDefinition来做。
    在 配置文件中可以定义父和子,父用RootBeanDefinition表示, 而子用ChildBeanDefiniton表示,而没有父的就使用 RootBeanDefinition表示。

  5. 子接口:AnnotatedBeanDefinition
    增加了一个注解元数据AnnotationMetadata取得方法。

AnnotatedBeanDefinition的三个子类:

1.ScannedGenericBeanDefinition

存储@Component、@Service、@Controller等注解注释的类
它的源码很简单,就是多了一个AnnotationMetadata 属性,用来存储一些注解信息。

2. AnnotatedGenericBeanDefinition

在基于注解驱动的Spring应用着,它使用得非常的多。因为获取注解信息非常的方便。
AnnotatedGenericBeanDefinition只能用于已经被注册或被扫描到的类。

3.ConfigurationClassBeanDefinition

首先需要注意的是,它是ConfigurationClassBeanDefinitionReader的一个私有的静态内部类:这个类负责将@Bean注解的方法转换为对应的ConfigurationClassBeanDefinition类。

ConfigurationClassBeanDefinition直接继承自RootBeanDefinition

它有一些默认的设置处理如下:
@Bean注解没有指定bean的名字,默认会用方法的名字命名bean
@Configuration注解的类会成为一个工厂类,而所有的@Bean注解的方法会成为工厂方法,通过工厂方法实例化Bean,而不是直接通过构造函数初始化(所以我们方法体里面可以很方便的书写逻辑。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值