Spring 容器注入时查找 Bean 的完整规则

Spring 容器注入时查找 Bean 的完整规则

彻底搞懂 Spring IoC 在运行时到底“先找谁、再找谁、如何决策”,一文掌握源码级细节。


一、为什么要谈“查找规则”?

在 Spring 应用中,我们最常见的代码是:

@Autowired
private OrderService orderService;

容器启动后,Spring 必须回答两个问题:

  1. 有哪些候选 Bean?
  2. 最终注入哪一个?

这两个问题的答案,就是 Spring 容器注入时查找 Bean 的完整规则


二、整体流程(源码视角)

AbstractBeanFactory#doGetBean
  └── DefaultListableBeanFactory#resolveDependency
        ├── 1️⃣ 按类型找候选   (findAutowireCandidates)
        ├── 2️⃣ 过滤歧义       (QualifierAnnotationAutowireCandidateResolver)
        ├── 3️⃣ 确定唯一       (determineAutowireCandidate)
        └── 4️⃣ 创建或返回     (getBean → createBean)

三、四步查找规则详解

① 按类型找候选(findAutowireCandidates)

  • 输入:接口/类 Class<?> requiredType
  • 输出Map<String, Object> —— beanName → Bean 实例
  • 规则
    • 递归 所有父容器(父子上下文场景)
    • 包含 FactoryBean#getObjectType 返回的类型
    • 过滤 抽象、非单例、非自动装配候选 (isAutowireCandidate)

② 过滤歧义(QualifierAnnotationAutowireCandidateResolver)

  • @Qualifier 精确匹配
  • @Primary 标记首选
  • 自定义限定符注解(元注解 @Qualifier
  • 变量名与 beanName 匹配

③ 确定唯一(determineAutowireCandidate)

候选数决策路径结果
0NoSuchBeanDefinitionException注入失败
1直接返回唯一 Bean成功
>1继续 ② 规则,直到只剩 1 个成功
仍 >1NoUniqueBeanDefinitionException注入失败

④ 创建或返回(getBean)

  • 单例已存在 → 直接返回
  • 单例不存在 → 走 完整生命周期(实例化 → 依赖注入 → 初始化 → 暴露)

四、候选来源总览

来源如何注册默认 beanName
@Component 扫描类路径扫描首字母小写类名
@Bean 方法@Configuration 解析方法名
XML <bean>BeanDefinitionReaderid 或类名
spring.factoriesImportSelector全限定类名
手动注册BeanDefinitionRegistry显式指定

五、歧义消除的 4 种官方姿势

方式示例优先级
@Qualifier@Qualifier("stripe")最高
变量名匹配PaymentService stripe;次高
@Primary@Primary @Service兜底
List/MapList<PaymentService>全部注入

六、一张脑图速记

注入点 @Autowired
    ↓
resolveDependency(requiredType)
    ├─ 1️⃣ findAutowireCandidates()
    │    ├─ 扫描所有 BeanDefinition
    │    ├─ FactoryBean 代理类型
    │    └─ 过滤非候选
    ├─ 2️⃣ checkQualifiers()
    │    ├─ @Qualifier
    │    ├─ @Primary
    │    └─ 变量名
    ├─ 3️⃣ determineAutowireCandidate()
    │    ├─ 0 → NoSuch
    │    ├─ 1 → OK
    │    └─ >1 → NoUnique
    └─ 4️⃣ getBean()
         ├─ 已存在单例 → 直接返回
         └─ 不存在 → 创建

七、一句话总结

Spring 容器注入时查找 Bean 的完整规则 就是:
“先按类型找出所有候选,再用 @Qualifier/@Primary/变量名 逐级过滤,最终只剩一个 Bean 才注入;否则抛异常。”
记住这 4 步,任何注入失败都能 30 秒内定位。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半部论语

如果觉得有帮助,打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值