Appearance
BeanDefinition源码分析
一、BeanDefinition的核心定位:Bean的"元数据蓝图"
在Spring IOC容器中,BeanDefinition是描述Bean的所有元数据的对象,相当于Bean的"设计图纸"。容器通过它来了解:
- Bean的类型(class);
- Bean的作用域(scope,如singleton/prototype);
- Bean的生命周期(初始化/销毁方法、延迟加载);
- Bean的依赖关系(构造器参数、属性值、依赖的Bean);
- Bean的扩展配置(方法覆盖、自动装配模式、工厂方法等)。
简单来说:Bean = BeanDefinition + 容器的实例化逻辑。容器启动时,先加载所有BeanDefinition,再根据其描述创建Bean实例。
二、BeanDefinition的接口体系
Spring通过接口分层定义了BeanDefinition的核心能力,其继承关系如下:
BeanDefinition
├─ AbstractBeanDefinition(抽象实现,核心基类)
├─ RootBeanDefinition(顶层BeanDefinition,无父类)
├─ ChildBeanDefinition(子类BeanDefinition,必须有父类)
└─ GenericBeanDefinition(Spring 2.5+推荐,替代Root/Child,支持动态父类)
└─ AnnotatedBeanDefinition(扩展接口,支持注解元数据,如@Component/@Bean)
└─ ScannedGenericBeanDefinition(扫描@Component注解生成的BeanDefinition)
└─ ConfigurationClassBeanDefinition(@Configuration类中的@Bean方法生成的BeanDefinition)
1. 核心接口:BeanDefinition
org.springframework.beans.factory.config.BeanDefinition
定义了Bean元数据的最小集,关键方法如下:
java
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 作用域相关
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// Bean角色(用于区分用户定义的Bean和框架内部Bean)
int ROLE_APPLICATION = 0; // 用户应用Bean
int ROLE_SUPPORT = 1; // 框架支持Bean(如ApplicationContext内部Bean)
int ROLE_INFRASTRUCTURE = 2; // 框架基础设施Bean(如BeanPostProcessor)
// 设置/获取Bean的类名(注意:是类的全限定名,而非Class对象)
void setBeanClassName(String beanClassName);
String getBeanClassName();
// 设置/获取作用域(默认singleton)
void setScope(String scope);
String getScope();
// 设置/获取延迟加载(默认false,即容器启动时创建singleton Bean)
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 设置/获取依赖的Bean名称(依赖的Bean必须先初始化)
void setDependsOn(String... dependsOn);
String[] getDependsOn();
// 设置/获取是否自动装配到其他Bean(默认false)
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
// 设置/获取是否为主要Bean(当多个Bean满足自动装配条件时,优先选择主要Bean)
void setPrimary(boolean primary);
boolean isPrimary();
// 设置/获取工厂Bean名称(如果当前Bean是通过工厂Bean创建的)
void setFactoryBeanName(String factoryBeanName);
String getFactoryBeanName();
// 设置/获取工厂方法名称(如果当前Bean是通过工厂方法创建的)
void setFactoryMethodName(String factoryMethodName);
String getFactoryMethodName();
// 获取构造器参数(用于构造器注入)
ConstructorArgumentValues getConstructorArgumentValues();
// 获取属性值(用于setter注入)
MutablePropertyValues getPropertyValues();
// 设置/获取初始化方法名称(如init-method="init")
void setInitMethodName(String initMethodName);
String getInitMethodName();
// 设置/获取销毁方法名称(如destroy-method="destroy")
void setDestroyMethodName(String destroyMethodName);
String getDestroyMethodName();
// 设置/获取Bean角色
void setRole(int role);
int getRole();
// 设置/获取描述信息(用于日志或错误提示)
void setDescription(String description);
String getDescription();
}
2. 抽象基类:AbstractBeanDefinition
org.springframework.beans.factory.support.AbstractBeanDefinition
是所有具体BeanDefinition的基类,实现了BeanDefinition的核心逻辑,并扩展了更多属性(如自动装配模式、方法覆盖、BeanClass缓存等)。其关键属性如下:
java
public abstract class AbstractBeanDefinition implements BeanDefinition, Cloneable {
// 自动装配模式(默认NO,即不自动装配)
public static final int AUTOWIRE_NO = 0; // 不自动装配
public static final int AUTOWIRE_BY_NAME = 1; // 按名称自动装配(属性名匹配Bean名称)
public static final int AUTOWIRE_BY_TYPE = 2; // 按类型自动装配(属性类型匹配Bean类型)
public static final int AUTOWIRE_CONSTRUCTOR = 3; // 按构造器自动装配(构造器参数类型匹配Bean类型)
public static final int AUTOWIRE_AUTODETECT = 4; // 自动检测(已过时,Spring 3.0+移除)
// 依赖检查模式(默认NONE,即不检查)
public static final int DEPENDENCY_CHECK_NONE = 0; // 不检查
public static final int DEPENDENCY_CHECK_OBJECTS = 1; // 检查对象类型依赖
public static final int DEPENDENCY_CHECK_SIMPLE = 2; // 检查简单类型依赖(如int、String)
public static final int DEPENDENCY_CHECK_ALL = 3; // 检查所有类型依赖
// 核心属性
private volatile Class<?> beanClass; // Bean的Class对象(延迟解析,避免提前加载类)
private String scope = SCOPE_SINGLETON; // 作用域(默认singleton)
private boolean lazyInit = false; // 延迟加载(默认false)
private int autowireMode = AUTOWIRE_NO; // 自动装配模式(默认不自动装配)
private int dependencyCheck = DEPENDENCY_CHECK_NONE; // 依赖检查模式(默认不检查)
private String[] dependsOn; // 依赖的Bean名称
private String factoryBeanName; // 工厂Bean名称
private String factoryMethodName; // 工厂方法名称
private ConstructorArgumentValues constructorArgumentValues; // 构造器参数
private MutablePropertyValues propertyValues; // 属性值(setter注入)
private MethodOverrides methodOverrides; // 方法覆盖(如lookup-method、replace-method)
private String initMethodName; // 初始化方法名称
private String destroyMethodName; // 销毁方法名称
private boolean enforceInitMethod = true; // 是否强制调用初始化方法(默认true)
private boolean enforceDestroyMethod = true; // 是否强制调用销毁方法(默认true)
private boolean synthetic = false; // 是否为合成Bean(框架生成的,非用户定义)
private int role = ROLE_APPLICATION; // Bean角色(默认用户应用Bean)
private String description; // 描述信息
private Resource resource; // 定义Bean的资源(如XML文件、类文件)
}
3. 具体实现类
- RootBeanDefinition:顶层BeanDefinition,无父类,是合并后的最终BeanDefinition(如子BeanDefinition合并父类后生成RootBeanDefinition)。
- ChildBeanDefinition:子类BeanDefinition,必须指定父BeanDefinition(
parentName
),用于继承父类的配置(如属性、作用域)。Spring 2.5+已被GenericBeanDefinition替代。 - GenericBeanDefinition:推荐的通用实现,支持动态设置父BeanDefinition(
setParentName
),灵活性更高。例如:javaGenericBeanDefinition gbd = new GenericBeanDefinition(); gbd.setBeanClassName("com.example.User"); gbd.setParentName("parentBean"); // 动态指定父Bean gbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
- AnnotatedBeanDefinition:支持注解元数据的扩展接口,其实现类如
ScannedGenericBeanDefinition
(扫描@Component注解生成)、ConfigurationClassBeanDefinition
(@Configuration类中的@Bean方法生成),用于保存注解信息(如@Scope、@Lazy)。
三、BeanDefinition的生命周期:从解析到使用
BeanDefinition的生命周期贯穿Spring容器初始化的全流程,关键步骤如下:解析(Parse)→ 注册(Register)→ 合并(Merge)→ 使用(Instantiate)。
1. 解析:从配置到BeanDefinition
Spring支持多种配置方式(XML、注解、JavaConfig),解析过程的核心是将配置信息转换为BeanDefinition。
(1)XML配置解析
以<bean>
标签为例,Spring通过XmlBeanDefinitionReader
读取XML文件,再通过BeanDefinitionParserDelegate
处理每个<bean>
标签,生成对应的BeanDefinition。
示例XML:
xml
<bean id="user" class="com.example.User" scope="prototype" lazy-init="true">
<property name="name" value="张三"/>
<property name="age" value="25"/>
<constructor-arg index="0" value="李四"/>
<depends-on="address"/>
</bean>
解析过程:
BeanDefinitionParserDelegate
会创建一个GenericBeanDefinition
;- 设置
beanClassName
为com.example.User
; - 设置
scope
为prototype
; - 设置
lazyInit
为true
; - 将
<property>
标签转换为MutablePropertyValues
(存储name=张三
、age=25
); - 将
<constructor-arg>
标签转换为ConstructorArgumentValues
(存储构造器参数李四
); - 设置
dependsOn
为address
(依赖address
Bean)。
(2)注解配置解析
以@Component
注解为例,Spring通过ClassPathScanningCandidateComponentProvider
扫描指定包,找到带@Component
注解的类,生成ScannedGenericBeanDefinition
。
示例类:
java
@Component
@Scope("prototype")
@Lazy(true)
public class User {
@Value("张三")
private String name;
@Value("25")
private int age;
}
解析过程:
- 扫描到
User
类,创建ScannedGenericBeanDefinition
; - 设置
beanClassName
为com.example.User
; - 从
@Scope
注解获取scope
为prototype
; - 从
@Lazy
注解获取lazyInit
为true
; - 从
@Value
注解获取属性值,转换为MutablePropertyValues
(存储name=张三
、age=25
)。
(3)JavaConfig解析
以@Configuration
和@Bean
注解为例,Spring通过ConfigurationClassPostProcessor
(BeanFactoryPostProcessor)处理@Configuration
类,将@Bean
方法转换为ConfigurationClassBeanDefinition
。
示例类:
java
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
@Lazy(true)
public User user() {
User user = new User();
user.setName("张三");
user.setAge(25);
return user;
}
}
解析过程:
ConfigurationClassPostProcessor
扫描到AppConfig
类,处理@Bean
方法user()
;- 创建
ConfigurationClassBeanDefinition
,设置beanClassName
为com.example.User
; - 从
@Scope
注解获取scope
为prototype
; - 从
@Lazy
注解获取lazyInit
为true
; - 将
user()
方法的返回值作为Bean实例(通过工厂方法创建)。
2. 注册:将BeanDefinition存入容器
解析生成的BeanDefinition会被注册到BeanDefinitionRegistry
(BeanDefinition的注册中心)。BeanDefinitionRegistry
是一个接口,其核心实现是DefaultListableBeanFactory
(Spring默认的BeanFactory),它通过beanDefinitionMap
(Map<String, BeanDefinition>
)存储所有BeanDefinition。
注册过程示例:
java
// 1. 创建BeanFactory(默认是DefaultListableBeanFactory)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建BeanDefinition(以GenericBeanDefinition为例)
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClassName("com.example.User");
gbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
gbd.getPropertyValues().add("name", "张三");
// 3. 注册BeanDefinition到BeanFactory
beanFactory.registerBeanDefinition("user", gbd);
注意:注册时会检查beanName
是否重复,若重复且allowBeanDefinitionOverriding
(默认true
)为true
,则覆盖旧的BeanDefinition。
3. 合并:处理父BeanDefinition
当BeanDefinition有父类(如ChildBeanDefinition
、GenericBeanDefinition
指定了parentName
)时,Spring会合并父类和子类的配置,生成RootBeanDefinition(最终用于实例化的BeanDefinition)。
合并逻辑:
- 子类的属性会覆盖父类的同名属性(如子类设置了
scope=prototype
,父类设置了scope=singleton
,则子类的scope
生效); - 父类的
propertyValues
、constructorArgumentValues
会合并到子类(子类未设置的属性用父类的); - 父类的
methodOverrides
、dependsOn
等配置会合并到子类。
示例:
java
// 父BeanDefinition(singleton,name=父类)
GenericBeanDefinition parentGbd = new GenericBeanDefinition();
parentGbd.setBeanClassName("com.example.User");
parentGbd.setScope(BeanDefinition.SCOPE_SINGLETON);
parentGbd.getPropertyValues().add("name", "父类");
// 子类BeanDefinition(prototype,name=子类,父类=parentGbd)
GenericBeanDefinition childGbd = new GenericBeanDefinition();
childGbd.setParentName("parentGbd");
childGbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
childGbd.getPropertyValues().add("age", 25);
// 合并子类和父类,生成RootBeanDefinition
RootBeanDefinition mergedRbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition("childGbd");
// 合并后的结果:
// scope=prototype(子类覆盖父类)
// propertyValues={name=父类, age=25}(父类和子类合并)
4. 使用:根据BeanDefinition实例化Bean
容器启动时(或第一次获取Bean时,若lazyInit=true
),Spring会根据合并后的RootBeanDefinition实例化Bean,流程如下:
- 实例化:通过反射或工厂方法创建Bean实例(如
User user = new User()
); - 属性注入:将
propertyValues
中的属性值注入到Bean实例(如user.setName("张三")
); - 初始化:调用初始化方法(如
init-method
、InitializingBean.afterPropertiesSet()
); - 缓存:若
scope=singleton
,将Bean实例存入singletonObjects
缓存(Map<String, Object>
); - 销毁:当容器关闭时(若
scope=singleton
),调用销毁方法(如destroy-method
、DisposableBean.destroy()
)。
四、BeanDefinition的扩展:后置处理与动态修改
Spring提供了BeanFactoryPostProcessor接口,允许在BeanDefinition注册后、Bean实例化前修改BeanDefinition的元数据。这是Spring框架的核心扩展点之一。
1. 示例:修改属性值
java
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 获取名为"user"的BeanDefinition
BeanDefinition userBD = beanFactory.getBeanDefinition("user");
// 修改属性值(将name从"张三"改为"李四")
userBD.getPropertyValues().add("name", "李四");
// 修改作用域(从prototype改为singleton)
userBD.setScope(BeanDefinition.SCOPE_SINGLETON);
}
}
2. 示例:动态注册BeanDefinition
java
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 动态创建BeanDefinition(User类)
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClassName("com.example.User");
gbd.getPropertyValues().add("name", "动态注册");
// 注册到容器
registry.registerBeanDefinition("dynamicUser", gbd);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 可选:修改已有的BeanDefinition
}
}
五、总结:BeanDefinition的核心价值
BeanDefinition是Spring IOC容器的核心元数据模型,其价值在于:
- 分离配置与实现:将Bean的配置(如类名、属性、作用域)与实现(类的代码)分离,提高灵活性;
- 支持多种配置方式:XML、注解、JavaConfig都能转换为BeanDefinition,统一容器的处理逻辑;
- 扩展能力:通过BeanFactoryPostProcessor可以动态修改BeanDefinition,满足复杂需求;
- 生命周期管理:容器通过BeanDefinition控制Bean的实例化、初始化、销毁过程,实现依赖注入、AOP等核心功能。
六、源码阅读建议
若要深入理解BeanDefinition的源码,建议从以下类入手:
- BeanDefinition接口:
org.springframework.beans.factory.config.BeanDefinition
(核心方法); - AbstractBeanDefinition:
org.springframework.beans.factory.support.AbstractBeanDefinition
(核心属性与实现); - GenericBeanDefinition:
org.springframework.beans.factory.support.GenericBeanDefinition
(通用实现); - BeanDefinitionRegistry:
org.springframework.beans.factory.support.BeanDefinitionRegistry
(注册中心接口); - DefaultListableBeanFactory:
org.springframework.beans.factory.support.DefaultListableBeanFactory
(BeanFactory的默认实现,存储BeanDefinition的beanDefinitionMap
); - XmlBeanDefinitionReader:
org.springframework.beans.factory.xml.XmlBeanDefinitionReader
(XML配置解析); - ClassPathScanningCandidateComponentProvider:
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
(注解扫描解析)。
通过以上分析,相信你对Spring的BeanDefinition有了更深入的理解。BeanDefinition是Spring框架的"基石",掌握它能帮助你更好地理解Spring IOC容器的工作机制,以及扩展Spring框架的能力。