ComponentScan注解
  1. @ComponentScan 用法1:
package com.niewj.config;import com.niewj.bean.Person;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.FilterType;import org.springframework.stereotype.Controller;@Configuration@ComponentScan("com.niewj")public class MainConfig {    @Bean    public Person person() {        return new Person("張三", 22);    }}

(0). 惯例: @ComponentScan(value="com.niewj")

(1). FilterType.ANNOTATION 只排除注解 value + excludeFilters

@ComponentScan( // 只排除:        value = "com.niewj",        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})

(2).FilterType.ANNOTATION 只过滤注解: 须要加上 value + useDefaultFilters=false + includeFilters

@ComponentScan( // 只蕴含: 必须要写 useDefaultFilters 否则不失效        value = "com.niewj",        useDefaultFilters = false,        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)})

(3). FilterType.ASSIGNABLE_TYPE :制订具体的类型, includeFilters 和 excludeFilters 自身就是个数组!

@ComponentScan( // 只蕴含: 必须要写 useDefaultFilters 否则不失效        value = "com.niewj",        useDefaultFilters = false,        includeFilters = {                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BookService.class)        })
  1. 自定义 TypeFilter @ComponentScan 用法:
@Testpublic void testTypeFilter() {    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);    Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);}

输入如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorymainConfigbookControllerperson

MainConfig.java:

package com.niewj.config;import com.niewj.bean.Person;import com.niewj.util.MyComponentScanTypeFilter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.FilterType;@Configuration@ComponentScan(value = "com.niewj",        useDefaultFilters = false,        includeFilters = {                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyComponentScanTypeFilter.class)        })public class MainConfig {    @Bean    public Person person() {        return new Person("張三", 22);    }}

次要看 MyComponentScanTypeFilter的类申明: 它的判断逻辑是满足一下两点, 则匹配!

  1. 如果类有注解@Controller
  2. 如果类是BaseController的子类
package com.niewj.util;import com.niewj.controller.BaseController;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;/** * 自定义 ComponentScan形式: */public class MyComponentScanTypeFilter implements TypeFilter {    /**     * 此处的判断逻辑是:     * 如果     * 1. 类是BaseController的子类     * 2. && 注解蕴含@Controller, 则匹配!     *     * @param metadataReader        获取到的以后类的注解信息     * @param metadataReaderFactory 可获取到其余类信息的工厂     * @return     * @throws IOException     */    @Override    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {        // 1. 获取以后类的注解信息        AnnotationMetadata annoMetadata = metadataReader.getAnnotationMetadata();        // 2. 获取以后正在扫描的类信息:        ClassMetadata classMetadata = metadataReader.getClassMetadata();        if (isBaseController(classMetadata) && hasControllerAnnotation(annoMetadata)) {            return true;        }        return false;    }    /**     * 条件1: 正在扫描的类 是不是 BaseController的子类     *     * @param classMetadata     * @return     */    private boolean isBaseController(ClassMetadata classMetadata) {        // 3. 正在扫描的类名称        String className = classMetadata.getClassName();        // 4. 正在扫描的类的父类, 格局: BookController->com.niewj.controller.BaseController        String superClassName = classMetadata.getSuperClassName();        return superClassName.contains(BaseController.class.getSimpleName());    }    /**     * 判断注解中有无Controller "org.springframework.stereotype.Controller"     *     * @param annotationMetadata     * @return     */    private boolean hasControllerAnnotation(AnnotationMetadata annotationMetadata) {        return annotationMetadata.getAnnotationTypes().stream().anyMatch(e -> e.equals("org.springframework.stereotype.Controller"));    }}

小结: ComponentScan扫描大抵罕用有这么几类:

1.一般@ComponentScan(value="com.niewj")

2.注解过滤排除: @ComponentScan(value="com.niewj", excludeFilters={filter1, filter2,...})

3.注解过滤蕴含: @ComponentScan(value="com.niewj", includeFilters={filter1, filter2, ...})

其中的 Filter 蕴含

(1). 注解过滤匹配: type = FilterType.ANNOTATION
(2). 指定的类名比配: type=FilterType.ASSIGNABLE_TYPE
(3).自定义类型匹配: type=FilterType.CUSTOM 如示例中的:

MyComponentScanTypeFilter implements `TypeFilter`

(4). type=FilterType.ASPECTJ (不罕用)
(5). 正则匹配 type=FilterType.REGEX (不罕用)