Spring IOC 容器 **默认注册 Bean** 的 8 条规则

Spring IOC 容器 默认注册 Bean 的 8 条规则

(Spring Framework 6.x 源码级总结)

阅读提示:把下面 8 条规则背下来,再读 Spring 源码时,你会在任何一行代码里立刻知道「这个 BeanDefinition 是从哪儿来的」。


1️⃣ 环境扫描:从 启动类所在包 向下递归

  • @SpringBootApplication 内隐含 @ComponentScan 无参数 → 扫描当前包及其子包。
  • 源码位置:ComponentScanAnnotationParser#parse()ClassPathBeanDefinitionScanner#doScan()

2️⃣ 类级别注解 自动注册

遇到下列注解即注册为 singleton Bean:

  • @Component(含 @Service@Repository@Controller 等元注解)
  • @Configuration(特殊:还会生成 CGLIB 代理,见规则 4)
  • @Bean 方法所在类如果被 @Configuration 标注,则方法返回值也被注册。

3️⃣ @Bean 方法 注册规则

  • 作用域 :默认 singleton;可通过 @Scope 覆盖。
  • 名字
    • 显式 value/name → 直接使用
    • 空 → 方法名首字母小写
  • 重载保护 :同名 Bean 后注册的覆盖先注册的(DefaultListableBeanFactory#registerBeanDefinition 抛异常 → 允许覆盖开关 spring.main.allow-bean-definition-overriding=true)。

4️⃣ @Configuration 特殊逻辑

  • 类本身注册为 lite @Component
  • 同时注册 ConfigurationClassPostProcessor ,它会:
    1. 解析 @Bean 方法
    2. 解析 @Import(普通类、ImportSelector、ImportBeanDefinitionRegistrar)
    3. 解析 @ComponentScan
    4. 生成 CGLIB 代理 保证 @Bean 方法内部依赖仍是单例。

5️⃣ @Import 的三类导入

类型 注册方式 示例
普通类 直接注册 singleton @Import(MyConfig.class)
ImportSelector selectImports() 返回 String[] @EnableCaching
ImportBeanDefinitionRegistrar 手动 registry.registerBeanDefinition() @EnableAspectJAutoProxy

6️⃣ SPI 机制spring.factories & META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

  • Spring Boot 启动时读取 spring.factoriesEnableAutoConfiguration 列表
  • 每个自动配置类内部再用 @Configuration + @Bean 注册大量基础设施(DataSource、WebMvc、Security...)。

7️⃣ FactoryBean & BeanFactoryPostProcessor

  • FactoryBean#getObject() 的返回值被注册,名字为 &beanName(取实际对象去掉 &)。
  • BeanFactoryPostProcessor(如 PropertySourcesPlaceholderConfigurer)可在注册阶段 修改新增 BeanDefinition。

8️⃣ 默认单例作用域 & 延迟初始化

  • 默认作用域:singleton
  • 默认非延迟 :容器启动即实例化;加 @Lazy 则延迟到首次调用 getBean()
  • 单例池:DefaultSingletonBeanRegistry#singletonObjects(ConcurrentHashMap)。

一张图总结

复制代码
启动类包扫描 → 类注解(@Component/@Configuration) → @Bean方法
               ↓
           @Import(三类) → @ComponentScan → spring.factories
               ↓
      ConfigurationClassPostProcessor → 注册所有BeanDefinition
               ↓
     DefaultListableBeanFactory#preInstantiateSingletons → 实例化

背完这 8 条,再读 Spring 源码时,你会在任意一行 registerBeanDefinition() 前立刻定位"这是哪条规则触发"。