1. 概述
在本篇文章中,我们将深入探讨 Spring 框架中的 UnsatisfiedDependencyException
异常:它的成因、常见触发场景以及如何避免这类问题。
2. UnsatisfiedDependencyException
的成因
顾名思义,当 Spring 容器无法满足某个 Bean 或属性的依赖关系时,就会抛出这个异常 ✅
通常发生在 Spring 尝试自动装配(autowire)一个 Bean 时,但无法解析其必须的依赖项 ❌
3. 示例应用结构
我们先来看一个简单的例子。假设有一个服务类 PurchaseDeptService
,它依赖于 InventoryRepository
接口:
@Service
public class PurchaseDeptService {
private final InventoryRepository repository;
public PurchaseDeptService(InventoryRepository repository) {
this.repository = repository;
}
}
public interface InventoryRepository {
}
@Repository
public class ShoeRepository implements InventoryRepository {
}
@SpringBootApplication
public class SpringDependenciesExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDependenciesExampleApplication.class, args);
}
}
目前这些类都放在同一个包 com.baeldung.dependency.exception.app
下,运行项目一切正常 ✅
但如果跳过某些配置步骤,就会踩坑了 ❌
4. 缺少组件注解
现在我们把 ShoeRepository
上的 @Repository
注解去掉:
public class ShoeRepository implements InventoryRepository {
}
再次启动项目,你会看到如下错误信息:
UnsatisfiedDependencyException: Error creating bean with name 'purchaseDeptService': Unsatisfied dependency expressed through constructor parameter 0
Spring 并没有被指示去创建并注册 ShoeRepository
这个 Bean,自然也无法注入,最终抛出了异常。
解决方案: 给 ShoeRepository
加上 @Repository
即可解决问题 ✅
5. 包扫描路径未覆盖
接下来我们将 ShoeRepository
和 InventoryRepository
移动到另一个包中:com.baeldung.dependency.exception.repository
此时再次运行程序,依旧会抛出 UnsatisfiedDependencyException
❌
这是因为 Spring Boot 默认只扫描主类所在包及其子包下的组件。
解决方案: 显式指定要扫描的包路径:
@SpringBootApplication
@ComponentScan(basePackages = {"com.baeldung.dependency.exception"})
public class SpringDependenciesExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDependenciesExampleApplication.class, args);
}
}
这样就能确保所有相关类都被正确加载进上下文 ✅
6. 多个候选 Bean 导致歧义
再加一个 InventoryRepository
的实现类 —— DressRepository
:
@Repository
public class DressRepository implements InventoryRepository {
}
这时再次运行项目,又会出现 UnsatisfiedDependencyException
❌
不过这次的问题是:存在多个符合条件的 Bean,Spring 不知道该选哪一个。
解决方法一:使用 @Qualifier
明确指定
给两个 Repository 添加不同的限定符:
@Qualifier("dresses")
@Repository
public class DressRepository implements InventoryRepository {
}
@Qualifier("shoes")
@Repository
public class ShoeRepository implements InventoryRepository {
}
然后在构造函数中也加上对应的限定符:
public PurchaseDeptService(@Qualifier("dresses") InventoryRepository repository) {
this.repository = repository;
}
这样一来,Spring 就知道应该注入的是 DressRepository
,问题迎刃而解 ✅
7. 总结
本文介绍了几种最常见的引发 UnsatisfiedDependencyException
的情况,并给出了相应的解决策略:
- ✅ 缺少必要的组件注解(如
@Service
,@Repository
) - ✅ 包扫描路径未覆盖目标类
- ✅ 存在多个相同类型的 Bean 导致依赖注入冲突
如果你对 Spring 的依赖注入机制还不太熟悉,建议参考我们更全面的教程:Spring BeanCreationException
文中涉及的所有代码都可以在 GitHub 上找到:GitHub 示例代码