本博客的demo源码
源码地址:https://github.com/nieandsun/spring-study
一、@ComponentScan的作用
- @ComponentScan注解有两个作用
- 扫描含有@Component,@Controller,@Service和@Repository的类,并将其注入到spring容器中。
- 扫描含有@Configuration的类,并使其生效。
二、demo的目录结构
三、@ComponentScan作用演示
- 扫描含有@Component,@Controller,@Service和@Repository的类,并将其注入到spring容器中。
相信大家都知道这个作用,这里不再演示,有需要的可以去我的github上下载源码,进行测试。
- 扫描含有@Configuration的类,并使其生效。
如上图所示,Config2可以扫描到config2_test目录,该目录下不仅含有@Component,@Controller,@Service和@Repository注解标注的四个类,还包含Config1配置类。Config1配置类,可以扫描到config1_test目录,并且里面还包含一个@Bean注解。
Config1配置类代码如上图所示
Config2配置类代码如下:
package com.nrsc.springstudy.c1_componentscan.config;
import com.nrsc.springstudy.c1_componentscan.config2_test.OrderRepository2;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
//标识此类为注解类
@Configuration
//扫描config2_test目录,并排除OrderRepository2类
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan.config2_test",
excludeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderRepository2.class})})
public class Config2 {
}
项目启动代码如下:
@Test
public void test02() {
//加载Config2配置类
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config2.class);
String[] names = ac.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
运行结果如下:
四、多个@ComponentScan以及@ComponentScans
- 结论:如果有多个@ComponentScan时,各个@ComponentScan扫描到的类的交集都会被注册到spring容器中。
具体代码不再展示,如demo的目录结构图所示,Config5配置类将扫描config5_test目录下除了OrderRepository5之外的类,Config5_1配置类只扫描OrderRepository5和BuyComponent5两个类,当按Config5配置类启动项目时,会把Config5_test目录下所有的类都注册到spring容器中,效果如下:
注意点----同一个配置类上多个@ComponentScan可能会报错
下面的配置类在我公司电脑的idea版本里是可以将config3_test目录下的所有类都注册到spring容器中,但是在我家里的电脑上以及另一个同事的电脑上会报编译期错误,代码运行也会出错。
package com.nrsc.springstudy.c1_componentscan.config;
import com.nrsc.springstudy.c1_componentscan.config3_test.OrderRepository3;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
//扫描整个config3_test目录
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan.config3_test")
//扫描除了OrderRepository3类之外的config3_test目录
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan.config3_test",
excludeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderRepository3.class})})
public class Config3 {
}
同事电脑上报错截图如下:
- 编译期异常
- 运行期异常
@ComponentScans的使用
由于同一个类上直接写多个@ComponentScan可能会报错,因此建议使用@ComponentScans,它可以解决直接在一个配置类上写多个@ComponentScan在有些电脑或idea版本上报错的问题,代码如下:
package com.nrsc.springstudy.c1_componentscan.config;
import com.nrsc.springstudy.c1_componentscan.config4_test.OrderRepository4;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
@ComponentScans(value = {
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan.config4_test"),
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan.config4_test",
excludeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderRepository4.class})})
})
public class Config4 {
}