SpringBoot源码解析(九):Bean定义接口体系

SpringBoot源码系列文章

SpringBoot源码解析(一):SpringApplication构造方法

SpringBoot源码解析(二):引导上下文DefaultBootstrapContext

SpringBoot源码解析(三):启动开始阶段

SpringBoot源码解析(四):解析应用参数args

SpringBoot源码解析(五):准备应用环境

SpringBoot源码解析(六):打印Banner

SpringBoot源码解析(七):应用上下文结构体系

SpringBoot源码解析(八):Bean工厂接口体系

SpringBoot源码解析(九):Bean定义接口体系


目录

前言

Spring容器的核心在于其对Bean的管理,而这一切的基础则由BeanDefinition接口体系所支撑。BeanDefinition作为描述定义Spring容器中Bean的核心接口,它不仅负责存储Bean的元数据,还为容器的实例化、依赖注入和生命周期管理提供了必要的信息。接下来我们将对其主要组件进行介绍。

一、BeanDefinition类图

二、BeanDefinition组件功能解析

1、AttributeAccessor(属性访问器)

AttributeAccessor是一个用于管理和操作键值对形式属性的接口,提供设置获取删除、检查属性等通用功能,广泛应用于Spring框架中元数据的管理

java 复制代码
public interface AttributeAccessor {
	// 设置属性
	void setAttribute(String name, @Nullable Object value);

	// 获取指定属性的值 
	@Nullable
	Object getAttribute(String name);

	// 如果该键对应的属性值已经存在,则直接返回现有值
	// 如果不存在,使用计算函数生成新值(相当于延迟计算,调用时候才计算)
	@SuppressWarnings("unchecked")
	default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
		...
	}

	// 移除指定键的属性并返回其值
	@Nullable
	Object removeAttribute(String name);

	// 检查指定键的属性是否存在
	boolean hasAttribute(String name);

	// 返回所有属性的键名称
	String[] attributeNames();
}

2、BeanDefinition(Bean定义)

AttributeAccessor是一个用于管理和操作键值对形式属性的接口,提供设置获取删除、检查属性等通用功能,广泛应用于Spring框架中元数据的管理

java 复制代码
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 单例作用域标识符:`singleton`(表示该 Bean 在整个容器生命周期内只有一个实例)
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	// 原型作用域标识符:`prototype`(表示每次获取该 Bean 时都会创建一个新实例)
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

	// 角色:应用程序 Bean(用于实现具体的业务逻辑)
	int ROLE_APPLICATION = 0;
	// 角色:支持 Bean(一些配合主逻辑使用的辅助工具或配置类)
	int ROLE_SUPPORT = 1;
	// 角色:基础设施 Bean(框架内部的实现类,比如事务管理器或事件监听器,这些 Bean 通常由 Spring 自动生成,用户无需关心)
	int ROLE_INFRASTRUCTURE = 2;


	// ==================== 可修改的属性 ====================


	// 设置父定义的名称(如果有)
	void setParentName(@Nullable String parentName);
	// 返回父定义的名称(如果有)
	@Nullable
	String getParentName();


	// 设置此 Bean 定义的类名
	void setBeanClassName(@Nullable String beanClassName);
	// 返回当前的 Bean 类名
	@Nullable
	String getBeanClassName();


	// 设置 Bean 的作用域(如 singleton 或 prototype)
	void setScope(@Nullable String scope);
	// 返回 Bean 当前的作用域
	@Nullable
	String getScope();

	// 设置是否延迟初始化(仅适用于单例 Bean)
	void setLazyInit(boolean lazyInit);
	// 返回该Bean是否延迟初始化(该Bean实际需要使用时才会被创建)
	boolean isLazyInit();


	// 设置此Bean依赖的其他 Bean 名称(Spring容器将确保这些依赖的Bean先被初始化)
	void setDependsOn(@Nullable String... dependsOn);
	// 返回此 Bean 依赖的其他 Bean 名称
	@Nullable
	String[] getDependsOn();


	// 设置此 Bean 是否可以作为自动装配的候选对象
	// 即:是否能够被Spring容器在自动装配过程中选中并注入到其他Bean中
	void setAutowireCandidate(boolean autowireCandidate);
	// 返回此 Bean 是否可以作为自动装配的候选对象
	boolean isAutowireCandidate();


	// 设置此 Bean 是否为主要的自动装配候选对象(在多个候选对象中优先选择primary候选)
	void setPrimary(boolean primary);
	// 返回此 Bean 是否为主要的自动装配候选对象
	boolean isPrimary();

	
	// 指定用于创建此 Bean 的工厂 Bean 名称(如果有)
	void setFactoryBeanName(@Nullable String factoryBeanName);
	// 返回用于创建此 Bean 的工厂 Bean 名称(如果有)
	@Nullable
	String getFactoryBeanName();
	// 指定用于创建此 Bean 的工厂方法名称(如果有)
	void setFactoryMethodName(@Nullable String factoryMethodName);
	// 返回用于创建此 Bean 的工厂方法名称(如果有)
	@Nullable
	String getFactoryMethodName();

	
	// 返回此 Bean 的构造函数参数值
	ConstructorArgumentValues getConstructorArgumentValues();
	// 检查是否为此 Bean 定义了构造函数参数值
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	
	// 返回当前 Bean 定义中的属性键值对集合,用于描述 Bean 初始化时需要注入的属性
	MutablePropertyValues getPropertyValues();
	// 检查是否为此 Bean 定义了属性值
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	
	// 设置初始化方法名称
	void setInitMethodName(@Nullable String initMethodName);
	// 返回初始化方法名称
	@Nullable
	String getInitMethodName();

	
	// 设置销毁方法名称
	void setDestroyMethodName(@Nullable String destroyMethodName);
	// 返回销毁方法名称
	@Nullable
	String getDestroyMethodName();

	
	// 设置此 Bean 定义的角色,上面常量的三种角色
	void setRole(int role);
	// 返回此 Bean 定义的角色
	int getRole();

	
	// 设置此 Bean 定义的人类可读描述
	void setDescription(@Nullable String description);
	// 返回此 Bean 定义的人类可读描述
	@Nullable
	String getDescription();


	// ==================== 只读属性 ====================

	
	// 解析和返回当前 Bean 定义的具体类型(包括泛型和复杂类型)
	ResolvableType getResolvableType();

	// 检查此 Bean 是否为单例
	boolean isSingleton();

	// 检查此 Bean 是否为原型
	boolean isPrototype();

	// 判断一个 Bean 定义是否为抽象定义,用于区分模板和具体实现
	boolean isAbstract();

	// 返回 Bean 定义的资源描述(通常是 XML 文件、Java 配置类、注解等)
	// 通过返回的描述,开发者可以了解这个 Bean 是从哪里加载的,便于定位问题
	@Nullable
	String getResourceDescription();

	// 它的作用是在Bean定义发生装饰、代理或重新定义时,提供对原始定义的访问
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();
}

3、AttributeAccessorSupport(属性访问器支持类)

AttributeAccessorSupport是Spring中的一个抽象类,用于管理任意键值对属性,提供添加、获取、移除等操作,常用于存储元数据动态属性信息。。

java 复制代码
public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {

	// 提供了一个内置的Map(attributes)来存储键值对属性
	private final Map<String, Object> attributes = new LinkedHashMap<>();

	// ...省略AttributeAccessor属性设置获取移除等方法的实现
}

4、BeanMetadataAttributeAccessor(Bean元数据属性访问器)

BeanMetadataAttributeAccessor是Spring框架中一个常用的工具类。它用于存储和管理与Bean元数据相关的附加属性,尤其是在Spring容器中扩展Bean定义时,作为元数据的容器。

java 复制代码
@SuppressWarnings("serial")
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {

	// 记录元数据元素的来源对象,可以是配置文件路径、注解类等
	@Nullable
	private Object source;
	
	// 设置此元数据元素的配置来源对象
	public void setSource(@Nullable Object source) {
		this.source = source;
	}
	// 获取此元数据元素的配置来源对象
	@Override
	@Nullable
	public Object getSource() {
		return this.source;
	}

	// 将给定的BeanMetadataAttribute添加到此访问器的属性集中
	public void addMetadataAttribute(BeanMetadataAttribute attribute) {
		// 将属性存储在父类提供的 attributes Map 中
		super.setAttribute(attribute.getName(), attribute);
	}

	// 在此访问器的属性集中查找给定的BeanMetadataAttribute
	@Nullable
	public BeanMetadataAttribute getMetadataAttribute(String name) {
		return (BeanMetadataAttribute) super.getAttribute(name);
	}

	// 设置属性,将其包装为BeanMetadataAttribute存储
	@Override
	public void setAttribute(String name, @Nullable Object value) {
		// 将属性值包装为 BeanMetadataAttribute
		super.setAttribute(name, new BeanMetadataAttribute(name, value));
	}

	// 获取指定名称的属性值
	@Override
	@Nullable
	public Object getAttribute(String name) {
		// 从父类的 attributes Map 获取 BeanMetadataAttribute
		BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.getAttribute(name);
		// 返回其值
		return (attribute != null ? attribute.getValue() : null);
	}

	// 移除指定名称的属性并返回其值
	@Override
	@Nullable
	public Object removeAttribute(String name) {
		// 从父类的 attributes Map 移除 BeanMetadataAttribute
		BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.removeAttribute(name);
		// 返回其值
		return (attribute != null ? attribute.getValue() : null);
	}
}

5、AbstractBeanDefinition(抽象Bean定义)

AbstractBeanDefinition是Spring中Bean定义抽象基类,提供了描述Bean的属性、依赖关系、作用域和生命周期等核心功能。

java 复制代码
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
	
	// ==================== 核心属性 ====================

	// Bean的类对象,可以是Class实例或类名字符串
    @Nullable
    private volatile Object beanClass; 
	
	// SCOPE_DEFAULT: 默认的Bean作用域名称为 "",等效于单例状态,除非被父Bean定义覆盖
    @Nullable
    private String scope = SCOPE_DEFAULT; 

	// 标记该Bean是否为抽象Bean,抽象Bean不能被实例化
    private boolean abstractFlag = false; 
	
	// 是否延迟初始化,null表示未明确设置
    @Nullable
    private Boolean lazyInit; 
	
	// 自动装配模式,默认不自动装配
    private int autowireMode = AUTOWIRE_NO; 
	
	// 依赖检查模式,默认无依赖检查
    private int dependencyCheck = DEPENDENCY_CHECK_NONE; 
	
	// 该Bean依赖的其他Bean名称
    @Nullable
    private String[] dependsOn; 
	
	// 是否为自动装配候选Bean
    private boolean autowireCandidate = true; 
	
	// 是否为主要的自动装配候选Bean
    private boolean primary = false; 
	
	// 工厂Bean的名称,如果通过工厂Bean创建
    @Nullable
    private String factoryBeanName; 
	
	// 工厂方法的名称,用于通过静态方法或工厂Bean的方法创建实例
    @Nullable
    private String factoryMethodName; 
	
	// 构造函数的参数值
    @Nullable
    private ConstructorArgumentValues constructorArgumentValues; 
	
	// Bean的属性值
    @Nullable
    private MutablePropertyValues propertyValues; 
	
	// 初始化方法名称,用于在Bean实例化后调用
    @Nullable
    private String initMethodName; 
	
	// 销毁方法名称,用于在Bean销毁前调用
    @Nullable
    private String destroyMethodName; 
	
	// Bean的角色,默认是应用角色
    private int role = BeanDefinition.ROLE_APPLICATION; 
	
	// Bean的描述信息
    @Nullable
    private String description; 
	
	// 描述该Bean定义来源的资源,例如XML配置文件的位置
    @Nullable
    private Resource resource; 

	// ==================== 核心方法 ====================
	
	// 都是类似的getset方法
	@Override
	public void setBeanClassName(@Nullable String beanClassName) {
		this.beanClass = beanClassName;
	}
	@Override
	@Nullable
	public String getBeanClassName() {
		Object beanClassObject = this.beanClass;
		if (beanClassObject instanceof Class) {
			return ((Class<?>) beanClassObject).getName();
		}
		else {
			return (String) beanClassObject;
		}
	}
	
	// 验证 Bean 定义是否有效,例如检查必须的属性是否已设置
	public void validate() throws BeanDefinitionValidationException {
		...
	}
	
	// 克隆当前 Bean 定义,用于 Bean 配置的复制
	public abstract AbstractBeanDefinition cloneBeanDefinition();
}

6、GenericBeanDefinition(通用Bean定义)

GenericBeanDefinition用于定义普通的Bean配置,适用于没有继承关系的独立Bean(虽然可以指定父 Bean,但通常不表示父子关系),支持配置构造方法、作用域、初始化方法等属性。

java 复制代码
@SuppressWarnings("serial")
public class GenericBeanDefinition extends AbstractBeanDefinition {

	@Nullable
	private String parentName; // 父类名称

	// 创建一个新的GenericBeanDefinition
	// 可通过其bean属性和配置方法进行配置
	public GenericBeanDefinition() {
		super();
	}

	// 创建一个新的GenericBeanDefinition,作为给定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; 
	}
	
	// 克隆 bean 定义
	@Override
	public AbstractBeanDefinition cloneBeanDefinition() {
		return new GenericBeanDefinition(this); 
	}
	
	// ... 省略重写 equal 和 toString方法
}

7、ChildBeanDefinition(子Bean定义)

ChildBeanDefinition专门用于表示子Bean的定义,允许子bean继承父bean的属性和方法,并可以进行扩展或覆盖。

java 复制代码
@SuppressWarnings("serial")
public class ChildBeanDefinition extends AbstractBeanDefinition {

	@Nullable
	private String parentName; // 父类名称
	
	// 为给定的父类创建一个新的 ChildBeanDefinition,提供构造函数参数和属性值
	public ChildBeanDefinition(
			String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

		super(cargs, pvs);
		this.parentName = parentName; // 设置父类名称
		setBeanClass(beanClass); // 设置 bean 类
	}

	// ... 省略类似构造方法
	
	// 设置父类名称
	@Override
	public void setParentName(@Nullable String parentName) {
		this.parentName = parentName; 
	}
	// 获取父类名称
	@Override
	@Nullable
	public String getParentName() {
		return this.parentName; 
	}
	
	// 校验父类必须存在,否则报错
	@Override
	public void validate() throws BeanDefinitionValidationException {
		super.validate();
		// 校验父类名称是否为空
		if (this.parentName == null) {
			throw new BeanDefinitionValidationException("'parentName' must be set in ChildBeanDefinition");
		}
	}
	
	// 克隆当前的 ChildBeanDefinition
	@Override
	public AbstractBeanDefinition cloneBeanDefinition() {
		return new ChildBeanDefinition(this); 
	}

	// ... 省略重写 equal 和 toString方法
}

8、RootBeanDefinition(根Bean定义)

RootBeanDefinition用于定义容器中的根级Bean配置,不能继承父Bean,是独立的顶级Bean定义类。

java 复制代码
@SuppressWarnings("serial")
public class RootBeanDefinition extends AbstractBeanDefinition {
	
	// 此属性用于保存一个被该bean定义装饰增强的Bean定义
	@Nullable
	private BeanDefinitionHolder decoratedDefinition; 
	
	// Bean定义的注解信息
	@Nullable
	private AnnotatedElement qualifiedElement; 

	...
	
	// 目标类型,表示包含泛型的类型
	@Nullable
	volatile ResolvableType targetType; 

	// 缓存解析后的目标类型
	@Nullable
	volatile Class<?> resolvedTargetType;

	// 缓存已解析的销毁方法的名称
	@Nullable
	volatile String resolvedDestroyMethodName;

	// 缓存解析后的构造函数或工厂方法
	@Nullable
	Executable resolvedConstructorOrFactoryMethod;

	// 缓存完全解析的构造函数参数
	@Nullable
	Object[] resolvedConstructorArguments;

	...

	// 创建一个新的 RootBeanDefinition,通过其 bean 属性和配置方法进行配置
	public RootBeanDefinition() {
		super();
	}
	// 创建一个新的RootBeanDefinition用于带有作用域的bean,通过给定的supplier构造每个实例
	public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {
		super();
		setBeanClass(beanClass);
		setScope(scope);
		setInstanceSupplier(instanceSupplier);
	}
	
	// ...省略其他构造方法

	// 省略了一些其他注释,以节省篇幅
	
	// 克隆 RootBeanDefinition
	@Override
	public RootBeanDefinition cloneBeanDefinition() {
		return new RootBeanDefinition(this); 
	}

	// ... 省略重写 equal 和 toString方法
}

9、AnnotatedBeanDefinition(注解Bean定义)

AnnotatedBeanDefinition是一个扩展了BeanDefinition的接口,用于访问与Bean类相关的注解元数据,如类级注解和工厂方法的元数据。

java 复制代码
public interface AnnotatedBeanDefinition extends BeanDefinition {

	// 获取当前Bean类的注解信息,允许在不加载类的情况下访问类级注解元数据
	AnnotationMetadata getMetadata();

	// 返回当前 Bean 定义的工厂方法的元数据,如果没有工厂方法则返回 null
	@Nullable
	MethodMetadata getFactoryMethodMetadata();
}

10、ScannedGenericBeanDefinition(扫描通用Bean定义)

ScannedGenericBeanDefinition是Spring中用于表示通过类路径扫描(如 @ComponentScan)发现的Bean的定义类,包含了扫描到的Bean类的元数据和配置信息。

java 复制代码
// 该类不会在早期加载Bean的Class,而是从 ".class" 文件本身解析所有相关的元数据,
// 使用 ASM ClassReader 进行解析
@SuppressWarnings("serial")
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

	// 存储扫描到的 Bean 类的注解元数据
	private final AnnotationMetadata metadata;

	// 为给定的 MetadataReader 描述的类创建一个新的 ScannedGenericBeanDefinition。
	public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
		// 校验 metadataReader 不为 null
		Assert.notNull(metadataReader, "MetadataReader must not be null");

		// 从 MetadataReader 获取注解元数据
		this.metadata = metadataReader.getAnnotationMetadata();
		// 设置 Bean 类的名称
		setBeanClassName(this.metadata.getClassName());
		// 设置扫描到的资源
		setResource(metadataReader.getResource());
	}

	@Override
	// 返回 Bean 类的注解元数据
	public final AnnotationMetadata getMetadata() {
		return this.metadata;
	}

	@Override
	@Nullable
	// 返回工厂方法的元数据(这里为 null,表示没有工厂方法)
	public MethodMetadata getFactoryMethodMetadata() {
		return null;
	}
}

总结

本文详细介绍了Spring框架中Bean的定义及其管理机制,重点阐述了BeanDefinition接口及其各个实现类的功能,包括属性访问Bean元数据管理父子Bean关系作用域依赖注入等方面的实现,旨在帮助开发者理解Spring容器如何通过这些机制来管理和配置Bean的生命周期。

相关推荐
飞翔的佩奇5 分钟前
Java项目: 基于SpringBoot+mybatis+maven+mysql实现的疾病防控综合管理系统(含源码+数据库+毕业论文)
java·数据库·spring boot·mysql·spring·毕业设计·疾病防控
power-辰南18 分钟前
技术架构师成长路线(2025版)
java·架构师·学习路线·技术专家
二十雨辰19 分钟前
[Java基础]面向对象
java·开发语言
栗豆包1 小时前
w187社区养老服务平台的设计与实现
java·spring boot·后端·spring·tomcat
violin-wang1 小时前
如何在Intellij IDEA中识别一个文件夹下的多个Maven module?
java·spring boot·spring·maven·intellij-idea
假客套1 小时前
Java小白入门教程:LinkedList
java·开发语言
lingllllove2 小时前
Maven的三种项目打包方式——pom,jar,war的区别
java·maven·jar
雨 子2 小时前
Maven jar 包下载失败问题处理
java·maven·jar
为美好的生活献上中指2 小时前
java每日精进1.31(SpringSecurity)
java·开发语言·微服务
星如雨グッ!(๑•̀ㅂ•́)و✧2 小时前
Spring Boot 2 快速教程:WebFlux处理流程(五)
java·spring boot·后端