1. 程式人生 > >spring註解 ComponentScan、自定義型別過濾器

spring註解 ComponentScan、自定義型別過濾器

        @ComponentScan註解,掃描哪些包下,將掃描到的包下的元件加入到容器中,這是一個常見的用法,如@ComponentScan(value = "me.xf"),對掃描到的包下的元件,處理哪些元件可以加入到容器中,哪些元件型別的,不可以加入到容器中,這裡引入了兩個ComponentScan的引數:excludeFilters和includeFilters。

        excludeFilters,在掃描到的包下,把哪些給排除掉。excludeFilters 是一個 ComponentScan.Filter[],Filter也是一個註解,接收的引數為要過濾的型別,要過濾的類型別。在Filter中,預設是過濾註解型別,可以改變FilterType的值,來更改過濾的型別,

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }

FilterType有以下幾個值:

public enum FilterType {
    ANNOTATION,
    ASSIGNABLE_TYPE,
    ASPECTJ,
    REGEX,
    CUSTOM;

    private FilterType() {
    }
}

        分別是按照註解型別、按照給定的型別、按照Aspectj型別、按照正則表示式以及自定義型別,常用的就是按照註解型別和自定義型別來進行過濾。

        使用自定義型別過濾,建立一個類,實現TypeFilter介面,複寫match方法,在match方法中,可以拿到類的資訊,從而定製自己的過濾規則:

public class MyTypeFilter implements TypeFilter {
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //獲得當前正在掃描的類的註解資訊
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //獲得當前正在掃描的類的資源資訊
        Resource resource = metadataReader.getResource();
        //獲得當前正在掃描的類的類資訊
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        String name = classMetadata.getClassName();
        System.out.println("掃描的類-->" + name);
        if(name.contains("Service")){
            System.out.println("匹配成功的類-->" + name);
            return true;
        }
        return false;
    }
}

        includeFilters和excludeFilters類似,只是作用和其相反,是將哪些元件給加入進來,區別在於,要多新增一個 useDefaultFilters = false 的引數。

       在配置類中,填寫好相應的引數即可使其生效

//配置類
@Configuration
@ComponentScan(value = "me.xf" , //掃描哪些包下的元件
//        excludeFilters = {      //在掃描的包下,排除哪些
//            @ComponentScan.Filter(type = FilterType.ANNOTATION , //過濾型別,註解型別
//                classes = {     //確定過濾的類
//                    Repository.class
//                }
//            )
//        },
//        includeFilters = {      //在掃描的包下,包含哪些
//            @ComponentScan.Filter(type = FilterType.ANNOTATION, //過濾型別
//                classes = {     //確定過濾的類
//                    Controller.class
//                }
//            )
//        }
        includeFilters = {
            @ComponentScan.Filter(type = FilterType.CUSTOM, //過濾型別,自定義型別
                classes = { //自定義的類,該類實現TypeFilter介面,複寫match方法,在方法中定義過濾的規則
                    MyTypeFilter.class
                }
            )
        }
        ,useDefaultFilters = false  //使用includeFilters時,要將useDefaultFilters設定為false
)
public class MyConfig {

    static {
        System.out.println("配置類載入...");
    }

    @Bean("person")   //預設為方法名小寫,返回的bean的id
    public Person getPerson(){
        System.out.println("向容器中新增person");
        return new Person("張三",20);
    }
}


//測試類
public class AnnotationTest {

    @Test
    public void testComponentScan(){
        System.out.println("======測試類開始======");
        ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println("======IOC容器建立完成======");
        String[] definitionNames = ctx.getBeanDefinitionNames();
        for (String name : definitionNames){
            System.out.println("bean 的定義名是:" + name);
        }
    }
}

測試輸出: