转载

Spring注解扫描@ComponentScan

当我们使用 Spring IOC 时,我们通常需要先在组件上添加模式注解,如 @Component、@Controller、@Service、@Repository、@Configuration 等将对象注入到 Spring 容器中,而这时程序需要知道它将扫描哪些组件.而 @ComponentScan 注解即用来作为这个边界划分的角色.而此注解也是使用xml配置文件 <context:component-scan/> 的替代.

1. 默认扫描

一般我们先创建一个配置类,并在配置类上添加 @ComponentScan 注解,给注解默认会扫描该类所在的包下所有的配置类,而这也是我们为什么一般默认将 SpringBoot 的引导类放在最外层的原因

@Configuration
@ComponentScan
public class SpringConfiguration {
    
}

----------------------------------------------------------------------------------------------------------------------

@org.junit.Test
    public void test2() throws IOException {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

Spring注解扫描@ComponentScan

2. 指定扫描

之前提到过, @ComponentScan 注解会默认扫描配置类所在包下的所有配置类,如果我们的配置类不是在最外层,那么我们就会出现在当前包以为的组件不能扫描到的情况发生.这时我们可以使用此注解的 value 属性值来指定需要扫描的包--- @Component("com.lsy") 就可以扫描指定包下的所有组件了.其次我们也可以使用此注解的 basePackage 属性,它是 value 属性的别名,另外使用 basePackages 属性我们则可以一次性指定多个包进行扫描

3. 过滤扫描

我们可以通过属性 excludeFiltersincludeFilters 来按照规则排除指定的组件扫描

excludeFilters
includeFilters

1. excludeFilters

@Configuration
@ComponentScan(value = "com.lsy",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class SpringConfiguration {

}

Spring注解扫描@ComponentScan

我们可以发现 Controller 标注的组件被排除在外了

2. includeFilters

@Configuration
@ComponentScan(value = "com.lsy",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class SpringConfiguration {

}

Spring注解扫描@ComponentScan

这里我们发现好像规则并没有起作用,其原因是: @Controller、@Service、@Repository、@Configuration 注解都是通过 @Component 派生出来的,所以他们除了是他们自身,同样是一个 @Component ,所以这里需要通过另一个属性 useDefaultFilters = false 才能得到我们想要的结果

@Configuration
@ComponentScan(value = "com.lsy",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)},useDefaultFilters = false)
public class SpringConfiguration {

}

Spring注解扫描@ComponentScan

4. 自定义规律规则

在之前的过滤扫描中我们使用了 @Filter 注解,此注解 type 属性是一个 FilterType 的枚举类型,一共 5 个值:

ANNOTATION
ASSIGNABLE_TYPE
ASPECTJ
REGEX
CUSTOM
@Configuration
@ComponentScan(value = "com.lsy",includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,value = {MyFilterType.class})},useDefaultFilters = false)
public class SpringConfiguration {

}

----------------------------------------------------------------------------------------------------------------------

public class MyFilterType implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前扫描到的组件的注解元数据
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

        //获取当前扫描到的组件的元数据
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        //获取当前扫描到的组件的资源信息
        Resource resource = metadataReader.getResource();
        if(classMetadata.getClassName().contains("User")){
            return true;
        }
        return false;
    }
}

Spring注解扫描@ComponentScan

首先我们将 @Filter 注解 type 属性值改为 CUSTOM ,并通过实现 TypeFilter 接口来自定义过滤规则,在此例中我们就能够只扫描类名中包含 User 字符串的组件

原文  https://segmentfault.com/a/1190000020802458
正文到此结束
Loading...