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. 包扫描路径未覆盖

接下来我们将 ShoeRepositoryInventoryRepository 移动到另一个包中: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 示例代码


原始标题:Unsatisfied Dependency in Spring