Bean 定义加载与注册
Bean 定义的加载是 Spring 容器初始化的核心环节,决定了哪些组件会被纳入容器管理。
BeanDefinition 结构
核心属性
Java
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// Bean 类名
String getBeanClassName();
// Scope(singleton/prototype)
String getScope();
// 是否延迟初始化
boolean isLazyInit();
// 依赖的 Bean
String[] getDependsOn();
// 是否 Primary
boolean isPrimary();
// 初始化方法
String getInitMethodName();
// 销毁方法
String getDestroyMethodName();
}
RootBeanDefinition
Java
RootBeanDefinition bd = new RootBeanDefinition(MyBean.class);
bd.setScope("singleton");
bd.setLazyInit(false);
bd.setInitMethodName("init");
bd.setDestroyMethodName("destroy");
registry.registerBeanDefinition("myBean", bd);
注解扫描加载
@ComponentScan 解析
Java
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
// 扫描器实现
public class ClassPathBeanDefinitionScanner {
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 查找候选组件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 注册 BeanDefinition
registerBeanDefinition(candidate, registry);
beanDefinitions.add(new BeanDefinitionHolder(candidate, beanName));
}
}
return beanDefinitions;
}
}
候选组件识别
Java
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
// 检查是否有 @Component 及衍生注解
return metadata.isIndependent() && (
metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))
);
}
@Configuration 类解析
ConfigurationClassPostProcessor
Java
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 1. 获取所有 @Configuration 类
Set<BeanDefinitionHolder> configCandidates = getConfigCandidates(registry);
// 2. 解析配置类
ConfigurationClassParser parser = new ConfigurationClassParser(...);
parser.parse(configCandidates);
// 3. 注册解析出的 BeanDefinition
ConfigurationClassBeanDefinitionReader reader = new ConfigurationClassBeanDefinitionReader(...);
reader.loadBeanDefinitions(parser.getConfigurationClasses());
}
配置类解析流程
Java
protected void processConfigurationClass(ConfigurationClass configClass) {
// 处理 @PropertySource
processPropertySource(configClass);
// 处理 @ComponentScan
processComponentScan(configClass);
// 处理 @Import
processImports(configClass);
// 处理 @ImportResource
processImportResource(configClass);
// 处理 @Bean 方法
processBeanMethods(configClass);
// 处理接口默认方法
processInterfaces(configClass);
}
@Import 处理机制
Import 类型
| 类型 | 说明 |
|---|---|
| @Import(Class) | 直接导入配置类 |
| ImportSelector | 按条件选择导入 |
| ImportBeanDefinitionRegistrar | 动态注册 BeanDefinition |
ImportSelector 实现
Java
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 根据注解属性动态返回类名
return new String[]{"com.example.ConfigA", "com.example.ConfigB"};
}
}
@Import(MyImportSelector.class)
@Configuration
public class AppConfig {
}
ImportBeanDefinitionRegistrar 实现
Java
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 动态注册 BeanDefinition
RootBeanDefinition bd = new RootBeanDefinition(MyBean.class);
registry.registerBeanDefinition("dynamicBean", bd);
}
}
@Bean 方法注册
@Bean 解析
Java
public void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata methodMetadata = beanMethod.getMetadata();
// 创建 BeanDefinition
BeanDefinition bd = new ConfigurationClassBeanDefinition(configClass, methodMetadata);
bd.setFactoryMethodName(methodMetadata.getMethodName());
bd.setFactoryBeanName(configClass.getBeanName());
// 处理属性
bd.setScope(methodMetadata.getScope());
bd.setLazyInit(methodMetadata.isLazyInit());
// 注册
registry.registerBeanDefinition(beanName, bd);
}
注册流程
BeanDefinitionRegistry
Java
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
void removeBeanDefinition(String beanName);
BeanDefinition getBeanDefinition(String beanName);
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
}
DefaultListableBeanFactory 注册
Java
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
// 检查 BeanName 唯一性
if (beanDefinition instanceof AbstractBeanDefinition) {
((AbstractBeanDefinition) beanDefinition).validate();
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 覆盖已有定义
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
// 新增定义
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
}
自动配置类加载
SpringBoot 自动配置
Java
// spring.factories 配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
// 加载流程
public class AutoConfigurationImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 1. 从 spring.factories 加载候选类
List<String> candidates = getCandidateConfigurations(annotationMetadata);
// 2. 过滤不符合条件的类
List<String> filtered = filterAutoConfiguration(candidates);
// 3. 返回符合条件的类名
return filtered.toArray(new String[0]);
}
}
注意:BeanDefinition 注册顺序影响依赖注入顺序,同名 Bean 会被覆盖。
要点总结
- BeanDefinition 描述 Bean 的元信息
- @ComponentScan 扫描注解组件并注册
- @Configuration 由 ConfigurationClassPostProcessor 解析
- @Import 支持类、Selector、Registrar 三种导入方式
- 自动配置类通过 spring.factories 加载
📝 发现内容有误?点击此处直接编辑