StackTraces
Spring Boot已验证

Spring Boot 报 NoSuchBeanDefinitionException

@debug_master32 天前更新阅读 6 min00

报 NoSuchBeanDefinitionException: No qualifying bean of type ... available 十有八九不是代码写错,是 Spring 压根没扫到这个类。Spring Boot 默认只扫描主类所在包和它的子包,Bean 定义在别的包、或少了 @Service 这类注解,容器里就没有它。

Issue & Env(案发现场与环境)

  • 业务场景:分模块或多包工程里,UserService 定义在一个包,UserController 在另一个包,注入时启动失败;或 Bean 类漏写 @Service / @Component。
  • 环境:Spring Boot 2.x / 3.x 通用。默认组件扫描行为由 @SpringBootApplication 里的 @ComponentScan 决定。

StackTrace(堆栈日志)

典型的注入失败堆栈,UnsatisfiedDependencyException 包着 NoSuchBeanDefinitionException:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController' defined in file [/Users/dev/demo/target/classes/com/example/demo/UserController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1388)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1341)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:612)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:962)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:930)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:596)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1307)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1296)
	at com.example.demo.Application.main(Application.java:12)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:2126)
	at org.springframework.beans.factory.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:2093)
	at org.springframework.beans.factory.DefaultListableBeanFactory.doResolveBeanForType(DefaultListableBeanFactory.java:1747)
	at org.springframework.beans.factory.DefaultListableBeanFactory.doResolveMultipleBeans(DefaultListableBeanFactory.java:1383)
	at org.springframework.beans.factory.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1313)
	at org.springframework.beans.factory.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1575)
	at org.springframework.beans.factory.DefaultListableBeanFactory.doResolveMultipleBeans(DefaultListableBeanFactory.java:1351)
	at org.springframework.beans.factory.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1313)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AutowireCapableBeanFactory.java:738)
	... 19 more

Reproduce(复现代码)

主类放在 com.example.demo,Service 却放在平级之外的 com.example.service:

// com/example/demo/Application.java
package com.example.demo;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
// com/example/service/UserService.java —— 在 com.example.demo 之外
package com.example.service;

@Service
public class UserService {
    public void hello() {}
}
// com/example/demo/UserController.java
package com.example.demo;

@RestController
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }
}

启动即抛上面那段 NoSuchBeanDefinitionException。UserService 有 @Service 注解,但它在默认扫描路径之外,容器没把它登记为 Bean。

Root Cause(根因分析)

@SpringBootApplication 是一个组合注解,其中包含 @ComponentScan。@ComponentScan 没有显式指定 basePackages 时,扫描起点是声明这个注解的类所在的包——也就是主类 Application 所在的 com.example.demo,以及它的所有子包。

com.example.service 和 com.example.demo 是平级兄弟包,既不是子包也不包含主类包,自然不在扫描范围内。于是 UserService 有注解也不会被 ClassPathScanningCandidateComponentProvider 找到,容器里没有「类型为 UserService 的 Bean」,注入时报 NoSuchBeanDefinitionException。

另一个高频变体是注解漏写:类没有 @Service / @Component / @Repository,即使在同一包内也不会被扫描登记。

还有一个更容易翻车的写法——把 @ComponentScan 的范围写错。spring-boot issue #16063 里,有人在主类上写 @ComponentScan("*.*"),扫描范围直接扩到整个依赖 jar,连 spring-boot-autoconfigure 里的自动配置类都被扫进去,报的是 BeanDefinitionStoreException。根子是同一个:@ComponentScan 的边界没搞清。

The Fix(解决方案)

首选:把 Bean 挪到主类包下面

最省事也最干净,让目录跟随主类包:

com.example.demo
├── Application.java
├── controller
│   └── UserController.java
└── service
    └── UserService.java

service 变成 com.example.demo 的子包,默认扫描能覆盖,无需任何额外配置。

跨包场景:显式声明扫描范围

Bean 在 Maven/Gradle 多模块或第三方包里,就主动扩大扫描范围:

@SpringBootApplication(scanBasePackages = {
    "com.example.demo",
    "com.example.service"
})
public class Application {}

或单独标注:

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.demo", "com.example.service"})
public class Application {}

注解漏写:补上 stereotype

确认类里有对应注解:

@Service
public class UserService { ... }

Mapper 接口这类非 @Component 的 Bean,配合 @MapperScan("com.example.demo.mapper") 显式指定扫描包,别指望默认组件扫描。

References(参考来源)

最后更新于 2026-09-09

这篇帮到你了吗?

刚解决了一个棘手的报错?花两分钟记录下来,帮助下一个遇到同样问题的开发者。

贡献一条解法