【Spring注解】@ComponentScan之includeFilters和excludeFilters

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

1. 概念

1.1 先看一段代码

【Spring注解】@ComponentScan之includeFilters和excludeFilters_第1张图片

1.2 type—FilterType

FilterType为一个枚举类,总共有5个值,也就是说type总共有5个可选值

public enum FilterType {
	ANNOTATION,//按照注解方式
	ASSIGNABLE_TYPE,//按照指定类型的方式
	ASPECTJ,//使用ASPECTJ表达式的方式-------没用过,不演示
	REGEX,//利用正则表达式进行指定-----------没用过,不演示
	CUSTOM//自己实现TypeFilter接口进行自定义规则(如下面的代码)
}

1.3 实现TypeFilter接口—自定义规则

下面的代码

  • 如果放在excludeFilters里,会过滤掉含有Buy字符的类-----即不扫描
  • 如果放在includeFilters里,会扫描含有Buy字符的类---------扫描
package com.nrsc.springstudy.c1_componentscan1.study2.config;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class NrscTypeFilter implements TypeFilter {

    private ClassMetadata classMetadata;

    /**
     * MetadataReader:读取到当前正在扫描类的信息
     * MetadataReaderFactory:可以获取到其他任何类信息
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类信息
        classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();

        String className = classMetadata.getClassName();
        System.out.println("----->" + className);
        //当类包含Buy字符, 则匹配成功,返回true
        //excludeFilters返回true---->会被过滤掉
        //includeFilters返回true---->会通过
        if (className.contains("Buy")) {
            return true;
        }
        return false;
    }
}

2 .代码演示—以excludeFilters为例

Config1配置类的代码如下图所示,代码中的NrscTypeFilter 即为上面的代码.
【Spring注解】@ComponentScan之includeFilters和excludeFilters_第2张图片
按照代码以及项目的目录结构可以猜出,config1_test中的类只有OrderController1能被注册到spring容器中.
【Spring注解】@ComponentScan之includeFilters和excludeFilters_第3张图片

3.includeFilters&useDefaultFilters = false

3.1 为何

  • 如下图,当使用includeFilters想只扫描含有@Service注解的类时,必须要加上useDefaultFilters = false

【Spring注解】@ComponentScan之includeFilters和excludeFilters_第4张图片
先验证一下效果
【Spring注解】@ComponentScan之includeFilters和excludeFilters_第5张图片
再简单说下原因:
其实@Component,@Controller,@Service和@Repository三者功能相同,后三个注解是为了对应后端代码的三层结构由第一个注解"复制"而来的.查看源码可以发现,后三个注解上面都有一个@Component.

  • 也就是说@Controller,@Service和@Repository除了是它们自己,也是一个@Component
  • 在进行includeFilters过滤时,如果useDefaultFilters =true,它会默认把所有包含@Component注解的类都进行扫描

因此只有加上useDefaultFilters=false才能得到正确的结果

3.2 多说几句

真的懂了上面我说的原因,你肯定就不会为使用下面的配置类,能扫描到所有含有@Component,@Controller,@Service和@Repository注解的类而疑惑了.

@Configuration
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan1.study2.config2_test",
        includeFilters = {
                @Filter(type = FilterType.ANNOTATION, classes = {Component.class})},
        useDefaultFilters = false)
public class Config3 {

你可能感兴趣的:(Spring)