目录
- 1. 整体流程概览
- 2. 详细步骤解析
- 2.1 扫描阶段:识别候选配置类
- 2.2 解析阶段:处理注解元数据
- (1) 解析@ComponentScan
- (2) 解析@Bean方法
- (3) 解析@Import
- (4) 处理父类与接口
- 2.3 注册阶段:加载BeanDefinition
- (1) 注册@Import的类
- (2) 注册@Bean方法
- (3) 处理嵌套配置类
- 3. 关键设计点
- (1) 延迟加载与递归处理
- (2) 元数据存储
- (3) 性能优化
- 4. 示hvrLrBFI例全流程
- 场景
- 步骤
- 5. 总结


在 Spring 中,@Configuration、@ComponentScan、@Bean、@Import 等注解的扫描、解析和 BeanDefinition 注册是一个分层处理的过程。下面我们以 @Configuration 类为例,结合代码流程详细说明其从扫描到注册的完整逻辑。
1. 整体流程概览
以下是核心步骤的流程图:
1. 扫描候选配置类 → 2. 解析注解元数据 → 3. 注册 BeanDefinition
具体分为以下阶段:
- 扫描阶段:通过 BeanDefinitionRegistry获取所有候选配置类。
- 解析阶段:使用 ConfigurationClassParser解析注解(如@ComponentScan、@Bean、@Import)。
- 注册阶段:通过 ConfigurationClassBeanDefinitionReader将解析结果注册为BeanDefinition。
2. 详细步骤解析
2.1 扫描阶段:识别候选配置类
触发入口:
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()逻辑:
- 从 BeanDefinitionRegistry获取所有已注册的BeanDefinition名称:String[] beanNames = registry.getBeanDefinitionNames(); 
- 遍历这些名称,检查对应的 BeanDefinition是否是候选配置类:- 条件:类上有 @Configuration、@Component、@ComponentScan、@Import、@ImportResource,或类中有@Bean方法。
- 判断逻辑:if (isFullConfigurationCandidate(beanDef) || isLiteConfigurationCandidate(beanDef)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanNpythoname)); }
- isFullConfigurationCandidate(beanDef):检查是否有- @Configuration注解。
- isLiteConfigurationCandidate(beanDef):检查是否有其他相关注解(如- @Component、- @Bean方法)。
 
- 条件:类上有 
关键点:
- 扫描的输入是已注册的 BeanDefinition(可能来自 XML、Java Config 或自动扫描)。
- 此时尚未解析注解内容,仅识别出需要进一步处理的候选类。
2.2 解析阶段:处理注解元数据
核心类:ConfigurationClassParser
parse()逻辑:递归解析每个候选配置类的注解。
(1) 解析@ComponentScan
- 作用:扫描指定包路径下的 @Component类(如@Service、@Repository)。
- 流程:- 获取 @ComponentScan注解的basePackages或basePackageClasses。
- 使用 ClassPathBeanDefinitionScanner扫描类路径:scanner.scan(basePackages); 
- 扫描到的类会被注册为新的 BeanDefinition(类型为ScannedGenericBeanDefinition)。
 
- 获取 
- 关键点:- 扫描时使用 ASM或反射读取类注解,避免提前加载类到 JVM。
- 新注册的 BeanDefinition可能也会被后续解析(如果它们也是配置类)。
 
- 扫描时使用 
(2) 解析@Bean方法
- 作用:将配置类中的 @Bean方法转换为BeanDefinition。
- 流程:- 遍历配置类中的所有方法,筛选带 @Bean注解的方法。
- 为每个 @Bean方法生成一个BeanDefinition:- 类型:ConfigurationClassBeanDefinition。
- 工厂方法:设置为 @Bean方法(通过factoryMethodName和factoryBeanName指定)。
- 依赖:解析 @Bean方法的参数(按类型或@Qualifier注入)。
 
- 类型:
 
- 遍历配置类中的所有方法,筛选带 
- 示例:@Configuration public class AppConfig { @Bean public DataSource dataSource() { return new HikariDataSource(); } }- 生成的 BeanDefinition会记录:factoryBeanName=appConfig,javascriptfactoryMethodName=dataSource。
 
- 生成的 
(3) 解析@Import
- 作用:动态导入其他配置类或 BeanDefinition。
- 三种处理方式:- 普通类:直接注册为 BeanDefinition。@Import(OtherConfig.class) 
- ImportSelector:通过编程方式选择要导入的类。- @Import(MyImportSelector.class) - MyImportSelector实现- selectImports()方法,返回要导入的类名数组。
 
- ImportBeanDefinitionRegistrar:直接注册- BeanDefinition。- @Import(MyRegistrar.class) - MyRegistrar实现- registerBeanDefinitions()方法,手动操作- BeanDefinitionRegistry。
 
 
- 普通类:直接注册为 
(4) 处理父类与接口
- 递归检查配置类的父类和接口,确保不遗漏任何 @Be编程客栈an方法或元注解。
2.3 注册阶段:加载BeanDefinition
核心类:ConfigurationClassBeanDefinitionReader
loadBeanDefinitions()逻辑:将解析结果(ConfigurationClass 对象)转换为 BeanDefinition 并注册到容器。
(1) 注册@Import的类
- 普通类:通过 registry.registerBeanDefinition()直接注册。
- ImportBeanDefinitionRegistrar:调用其- registerBeanDefinitions()方法。
(2) 注册@Bean方法
- 为每个 @Bean方法生成BeanDefinition并注册:for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); }
(3) 处理嵌套配置类
- 如果配置类内部有 @Configuration静态嵌套类,递归处理。
3. 关键设计点
(1) 延迟加载与递归处理
- 延迟加载:@ComponentScan扫描到的类可能也是配置类,需要递归解析。
- 循环依赖处理:Spring 通过提前暴露 BeanDefinition解决配置类之间的循环引用。
(2) 元数据存储
- ConfigurationClass对象存储解析后的中间结果(如- @Bean方法、- @Import类等)。
- BeanDefinition的- attribute字段存储配置类的元信息(如- @Lazy、- @Primary)。
(3) 性能优化
- ASM 字节码分析:在扫描阶段避免加载类到 JVM。
- 缓存:解析结果缓存到 ConfigurationClass中,避免重复处理。
4. 示例全流程
场景
@Configuration
@ComponentScan("com.example.service")
@Import(OtherConfig.class)
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}
步骤
- 扫描阶段:
- 发现 AppConfig是候选配置类(有@Configuration)。
 
- 发现 
- 解析阶段:- 解析 @ComponentScan:扫描com.example.service包,注册@Service类。
- 解析 @Import(OtherConfig.class):递归处理OtherConfig。
- 解析 @Bean dataSource():生成工厂方法BeanDefinition。
 
- 解析 
- 注册阶段:- 注册 OtherConfig及其@Bean方法。
- 注册 dataSource的BeanDefinition。
 
- 注册 
5. 总结
Spring 对配置类注解的处理是一个分层递归的过程:
- 扫描:通过 BeanDefin编程客栈itionRegistry筛选候选类。
- 解析:ConfigurationClassParser解析注解并生成中间结果(ConfigurationClass)。
- 注册:ConfigurationClassBeanDefinitionReader将解析结果转换为BeanDefinition。
这种设计将注解元数据解析与 BeanDefinition 注册分离,确保了灵活性和扩展性(如支持动态 ImportSelector)。同时,递归处理和缓存机制解决了复杂依赖和性能问题。
到此这篇关于Spring Boot 的注解生效详细步骤解析的文章就介绍到这了,更多相关Spring Boot 注解生效内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
 
         
                                         
                                         
                                         
                                         
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论