天天看点

【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans

本博客的demo源码

源码地址:https://github.com/nieandsun/spring-study

一、@ComponentScan的作用

  • @ComponentScan注解有两个作用
    • 扫描含有@Component,@Controller,@Service和@Repository的类,并将其注入到spring容器中。
    • 扫描含有@Configuration的类,并使其生效。

二、demo的目录结构

【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans

三、@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);
        }
    }
           

运行结果如下:

【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans

四、多个@ComponentScan以及@ComponentScans

  • 结论:如果有多个@ComponentScan时,各个@ComponentScan扫描到的类的交集都会被注册到spring容器中。

  具体代码不再展示,如demo的目录结构图所示,Config5配置类将扫描config5_test目录下除了OrderRepository5之外的类,Config5_1配置类只扫描OrderRepository5和BuyComponent5两个类,当按Config5配置类启动项目时,会把Config5_test目录下所有的类都注册到spring容器中,效果如下:

【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans

注意点----同一个配置类上多个@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 {
}
           

同事电脑上报错截图如下:

  • 编译期异常
【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans
  • 运行期异常
【Spring注解】@ComponentScan之 你可能没注意到的点本博客的demo源码一、@ComponentScan的作用二、demo的目录结构三、@ComponentScan作用演示四、多个@ComponentScan以及@ComponentScans

@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 {
}