Spring中@ComponentScan无法扫描到@Component注解类的问题
正在学习Marco Behler的《Confident Spring Professional》课程,仅使用spring context包开发。配置类MyFancyPdfInvoicesApplicationConfiguration添加了@ComponentScan(basePackageClasses = ApplicationLauncher.class)注解,UserService类也标注了@Component注解,但启动应用时始终报错:
No qualifying bean of type 'com.shatef.myfancyinvoices.service.UserService' available
相关代码
配置类代码
package com.shatef.myfancyinvoices.context; import com.fasterxml.jackson.databind.ObjectMapper; import com.shatef.myfancyinvoices.ApplicationLauncher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @ComponentScan(basePackageClasses = ApplicationLauncher.class) @Configuration public class MyFancyPdfInvoicesApplicationConfiguration { @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } }
UserService代码
package com.shatef.myfancyinvoices.service; import com.shatef.myfancyinvoices.model.User; import org.springframework.stereotype.Component; import java.util.UUID; @Component public class UserService { public User findById(String id) { String randomName = UUID.randomUUID().toString(); // always "finds" the user, every user has a random name return new User(id, randomName); } }
Servlet初始化代码
public class MyFancyPdfInvoicesServlet extends HttpServlet { private UserService userService; private ObjectMapper objectMapper; private InvoiceService invoiceService; @Override public void init() throws ServletException { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyFancyPdfInvoicesApplicationConfiguration.class); this.userService = ctx.getBean(UserService.class); this.objectMapper = ctx.getBean(ObjectMapper.class); this.invoiceService = ctx.getBean(InvoiceService.class); } }
错误堆栈信息
[INFO] [INFO] --- exec-maven-plugin:3.1.0:java (default-cli) @ myfancypdfinvoices --- Jan 28, 2023 1:44:26 AM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-nio-8080"] Jan 28, 2023 1:44:26 AM org.apache.catalina.core.StandardService startInternal INFO: Starting service [Tomcat] Jan 28, 2023 1:44:26 AM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet engine: [Apache Tomcat/9.0.54] Jan 28, 2023 1:44:27 AM org.apache.catalina.core.ContainerBase startInternal SEVERE: A child container failed during start java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]] at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) ... Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.shatef.myfancyinvoices.service.UserService' available at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean (DefaultListableBeanFactory.java:351) ...
以下是几种排查和解决方向:
1. 确认ApplicationLauncher的包路径
@ComponentScan(basePackageClasses = ApplicationLauncher.class)会扫描ApplicationLauncher所在包及其子包下的组件。如果ApplicationLauncher的包不是com.shatef.myfancyinvoices(根包),而是com.shatef.myfancyinvoices.launcher这类子包,那么com.shatef.myfancyinvoices.service不在扫描范围内。
- 解决:检查
ApplicationLauncher的package声明,确保它的包是所有需要扫描组件的父包;或者直接指定扫描的根包路径:@ComponentScan(basePackages = "com.shatef.myfancyinvoices")
2. 检查编译输出与类路径
Maven编译后,UserService的class文件可能未正确输出到target/classes目录,导致Spring无法找到该类。
- 解决:执行
mvn clean compile清理并重新编译项目,检查target/classes/com/shatef/myfancyinvoices/service/下是否存在UserService.class文件。
3. 确认InvoiceService的配置
代码中初始化Servlet时同时尝试获取InvoiceService,如果该类未标注@Component或不在扫描范围内,也会引发容器启动失败,表现为找不到UserService的错误。
- 解决:确认
InvoiceService类添加了@Component注解,且所在包在扫描范围内。
4. 显式指定扫描范围
如果上述方法无效,可在@ComponentScan中显式列出需要扫描的包:
@ComponentScan(basePackages = {"com.shatef.myfancyinvoices.service", "com.shatef.myfancyinvoices.context"})
5. 检查Spring依赖版本
若使用的Spring Context版本存在组件扫描相关bug,也可能导致无法识别@Component注解。
- 解决:确保使用稳定版Spring Context(如5.3.x及以上),检查pom.xml中的依赖配置,排除版本冲突。
内容的提问来源于stack exchange,提问作者Shady Atef

