ComponentScan注解
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);
}
}
(1). 常规: @ComponentScan(value="com.niewj")
`@ComponentScan(value="com.niewj")`
(2). FilterType.ANNOTATION
只排除注解:
`value` + `excludeFilters`
@ComponentScan( // 只排除:
value = "com.niewj",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)}
)
(3).FilterType.ANNOTATION
只过滤注解:
需要加上 `value` + `useDefaultFilters=false` + `includeFilters`
@ComponentScan( // 只包含: 必须要写 useDefaultFilters 否则不生效
value = "com.niewj",
useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)}
)
(4). 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)
}
)
(5). 自定义 TypeFilter @ComponentScan 用法:
@Test
public void testTypeFilter() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);
}
输出如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
person
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"));
}
}
(6). 小结:
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 (不常用)
备注: com.niewj也可以扫描到子包哦!
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hi@niewj.com