依赖查找和依赖注入均属控制反转(ioc)特性:前者是对象主动通过api(如getbean)查找依赖,耦合容器;后者是容器在创建对象时自动注入依赖,解耦彻底、推荐使用。

依赖查找和依赖注入,本质都是为了解耦对象之间的创建与使用关系,但思路相反:一个“主动要”,一个“被动给”。掌握这个区别,就抓住了面向对象中容器化管理变量的核心思想。
依赖查找:对象自己动手找依赖
依赖查找(Dependency Lookup)是指对象在运行时,通过容器提供的 API(比如 ApplicationContext.getBean())主动去获取它需要的协作对象。这种方式把“找谁”这件事留给了对象自身,容器只负责保管和生命周期管理。
- 典型写法:
userDao = context.getBean(UserDao.class)或context.getBean("userDao") - 优点是灵活可控,适合动态场景(比如根据条件加载不同实现)
- 缺点是代码耦合容器 API,无法脱离 Spring 环境独立测试或复用
- 在 Spring 中,BeanFactory 和 ApplicationContext 都支持 getBean(),但日常开发中不鼓励频繁手写这种调用
依赖注入:容器自动塞给你需要的依赖
依赖注入(Dependency Injection)是更主流、更推荐的方式。对象只需声明“我需要什么”,不关心“它从哪来”。容器在创建对象时,自动把符合要求的实例通过构造函数、setter 方法或字段注入进来。
- 构造器注入最稳妥:对象一建好就完整可用,依赖不可变,天然防空指针
- Setter 注入适合可选依赖或后期重配置(如开关切换数据源)
- 字段注入(@Autowired)最简洁,但隐藏了依赖关系,单元测试难 mock,Spring 官方文档已建议少用
- 注入依据默认是类型(byType),同类型多个 Bean 时需配合 @Qualifier 或 @Primary 指定
为什么推荐依赖注入而不是依赖查找?
关键在于“职责分离”和“可测试性”:
- 依赖注入让业务类彻底不知道容器的存在,只依赖接口或抽象,方便替换实现(比如用内存 Map 替代数据库 DAO 做快速测试)
- 依赖查找强制业务类持有 ApplicationContext 引用,等于把基础设施细节泄漏进业务逻辑
- Spring Boot 默认启用组件扫描和自动装配,意味着绝大多数场景下,你只要加 @Service、@Repository 和 @Autowired,容器就自动完成组装——这才是容器化管理变量的本意:省心、清晰、可预测
实际开发中怎么选?
绝大多数时候,用依赖注入;极少数场景才考虑依赖查找:
- 需要按运行时参数决定使用哪个 Bean(比如租户 ID 对应不同数据源)→ 用 ObjectProvider
延迟获取 - 框架扩展点(如自定义 BeanFactoryPostProcessor)→ 可能需临时查容器元信息
- 遗留系统改造过渡期 → 先保留部分 getBean(),逐步替换成注入
- 普通 service、controller、repository 层代码 → 坚决只用注入,不碰 getBean()










