ComponentScan注解
- @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) })
- 自定义 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的类申明: 它的判断逻辑是满足一下两点, 则匹配!
- 如果类有注解@Controller
- 如果类是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 (不罕用)