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(依赖addressBean)。
(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框架的能力。
