通过本文你将学到:
-
Component Scan
是什么? - 为什么
ComponentScan
很重要? - 项目中
Spring Boot
会对哪些包自动执行扫描(Component Scan
)? - 如何利用
Spring Boot
定义扫描范围? - 项目启动时关于
Component Scan
的常见报错
@ComponentScan
如果你理解了ComponentScan
,你就理解了Spring
Spring
是一个依赖注入(dependency injection
)框架。所有的内容都是关于bean
的定义及其依赖关系
定义Spring Beans
的第一步是使用正确的注解@Component
或@Service
或@Repository
但是,Spring
不知道你定义了某个bean
除非它知道从哪里可以找到这个bean
ComponentScan
做的事情就是告诉Spring
从哪里找到bean
由你来定义哪些包需要被扫描。一旦你指定了,Spring将会将在被指定的包及其下级包(sub packages
)中寻找bean
下面分别介绍在Spring Boot
项目和非Spring Boot
项目(如简单的JSP/Servlet
或者Spring MVC
应用)中如何定义Component Scan
Spring Boot
项目
总结:
- 如果你的其他包都在使用了
@SpringBootApplication
注解的main
app
所在的包及其下级包,则你什么都不用做,SpringBoot
会自动帮你把其他包都扫描了 - 如果你有一些
bean
所在的包,不在main
app
的包及其下级包,那么你需要手动加上@ComponentScan
注解并指定那个bean
所在的包
举个例子,看下面定义的类
package com.demo.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
ApplicationContext applicationContext =
SpringApplication.run(SpringbootApplication .class, args);
for (String name : applicationContext.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}
类 SpringbootApplication
在包下,这个类使用了
@SpringBootApplication
注解,该注解定义了Spring
将自动扫描包及其子包下的
bean
如果你项目中所有的类都定义在包及其子包下,那你不需要做任何事
但假如你一个类定义在包下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的。
方案1
定义@CoponentScan(“”)
这么做扫描的范围扩大到整个父包
@ComponentScan(“com.demo”)
@SpringBootApplication
public class SpringbootApplication {
方案2
定义分别扫描两个包@ComponentScan({“”,””})
@ComponentScan({"",""})
@SpringBootApplication
public class SpringbootApplication {
特别注意一下:如果使用了方案2,如果仅仅只写@ComponentScan({""})
将导致包下的类无法被扫描到(框架原始的默认扫描效果无效了)
非Spring Boot
项目
在非Spring Boot
项目中,我们必须显式地使用@ComponentScan
注解定义被扫描的包,可以通过XML
文件在应用上下文中定义或在Java
代码中对应用上下文定义
Java代码方式
@ComponentScan({".package1",".package2"})
@Configuration
public class SpringConfiguration {
XML文件方式
<context:component-scan base-package=".package1, .package2"/>
项目中常见关于Component Scan
的报错
你是否在项目启动中遇到过类似这样的报错:
WARNING: No mapping found for HTTP request with URI [/spring-mvc/login] in DispatcherServlet with name ‘dispatcher’
WARNING: No mapping found for HTTP request with URI [/list-todos] in DispatcherServlet with name ‘dispatcher’
或者:
ERROR:No qualifying bean of type [] found for dependency []: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@(required=true)}…
报错的根因都是bean没有被Spring找到
遇到这些错误你应该检查:
你是否给类加了正确的注解@Controller
,@Repository
,@Service
或@Component
你是否在应用上下文定义了Component Scan
报错类所在的包是否在Component Scan
中指定的包的范围@Component
和@ComponentScan
的区别@Component
和 @ComponentScan
的使用目的不一样
在某个类上使用@Component
注解,表明当需要创建类时,这个被注解的类是一个候选类。就像是举手。@ComponentScan
用于扫描指定包下的类。就像看都有哪些举手了。