当前位置: 首页 > web >正文

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 秒内定位。

http://www.xdnf.cn/news/16578.html

相关文章:

  • 动手学深度学习笔记04(上)
  • SPSC无锁环形队列技术(C++)
  • 深入解析MIPI C-PHY (四)C-PHY物理层对应的上层协议的深度解析
  • 电商平台中,订单未支付过期,如何实现自动关单?
  • C++ - 继承【下】
  • 将 JsonArray 类型的数据导出到Excel文件里的两种方式
  • 基于黑马教程——微服务架构解析(一)
  • 设计模式(十二)结构型:享元模式详解
  • Python day26
  • 无向图的连通性问题
  • 设计模式(十三)结构型:代理模式详解
  • spring gateway 配置http和websocket路由转发规则
  • NodeJs接入腾讯云存储COS
  • Ubuntu Linux 如何配置虚拟内存 —— 一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录8
  • USB设备调试
  • 全面理解JVM虚拟机
  • RK3568 Linux驱动学习——U-Boot使用
  • 六、搭建springCloudAlibaba2021.1版本分布式微服务-admin监控中心
  • Linux 基础命令大全
  • 内存泄漏问题排查
  • Context Engineering Notes
  • 【Golang】Go语言运算符
  • 迷宫生成与路径搜索(A算法可视化)
  • Triton IR
  • Libevent(4)之使用教程(3)配置
  • 如何使用ozone调试elf文件?
  • Dify 本地化部署深度解析与实战指南
  • LangChain实现RAG
  • 力扣 hot100 Day57
  • 第四科学范式(数据密集型科学):科学发现的新范式