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
在com.demo.springboot
包下,这个类使用了@SpringBootApplication
注解,该注解定义了Spring
将自动扫描包com.demo.springboot
及其子包下的bean
如果你项目中所有的类都定义在com.demo.springboot
包及其子包下,那你不需要做任何事
但假如你一个类定义在包com.demo.somethingelse
下,则你需要将这个新包也纳入扫描的范围,有两个方案可以达到这个目的。
方案1
定义@CoponentScan(“com.demo”)
这么做扫描的范围扩大到整个父包com.demo
@ComponentScan(“com.demo”)
@SpringBootApplication
public class SpringbootApplication {
方案2
定义分别扫描两个包
@ComponentScan({“com.demo.springboot”,”com.demo.somethingelse”})
@ComponentScan({"com.demo.springboot","com.demo.somethingelse"})
@SpringBootApplication
public class SpringbootApplication {
特别注意一下:如果使用了方案2,如果仅仅只写@ComponentScan({"com.demo.somethingelse"})
将导致com.demo.springboot
包下的类无法被扫描到(框架原始的默认扫描效果无效了)
非Spring Boot
项目
在非Spring Boot
项目中,我们必须显式地使用@ComponentScan
注解定义被扫描的包,可以通过XML
文件在应用上下文中定义或在Java
代码中对应用上下文定义
Java代码方式
@ComponentScan({"com.demo.package1","com.demo.package2"})
@Configuration
public class SpringConfiguration {
XML文件方式
<context:component-scan base-package="com.demo.package1, com.demo.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 [com.demo.springboot.jpa.UserRepository] found for dependency [com.demo.springboot.jpa.UserRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}…
报错的根因都是bean没有被Spring找到
遇到这些错误你应该检查:
你是否给类加了正确的注解@Controller
,@Repository
,@Service
或@Component
你是否在应用上下文定义了Component Scan
报错类所在的包是否在Component Scan
中指定的包的范围
@Component
和@ComponentScan
的区别
@Component
和 @ComponentScan
的使用目的不一样
在某个类上使用@Component
注解,表明当需要创建类时,这个被注解的类是一个候选类。就像是举手。
@ComponentScan
用于扫描指定包下的类。就像看都有哪些举手了。