全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

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 加载

📝 发现内容有误?点击此处直接编辑

← 上一篇 ApplicationContext 创建与刷新
下一篇 → SpringApplication 初始化
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库