基于ComponentScan注解的扫描范围及源码解析
作者:春秋战国程序猿
一.ComponentScan注解的默认扫描范围
ComponentScan注解的默认扫描范围是启动程序XxxApplication. java所在目录及其下的所有子包。
为了方便理解,我们看一下下面这个图片。
这个项目中的启动类是:SpringbootApplication.java
该启动类所在的目录是:springboot
那么ComponentScan注解的默认扫描范围是:springboot目录及其下面的所有子包。
二.如何修改ComponentScan注解的扫描范围
ComponentScan注解即可以扫描包,也可以扫描指定的类。
我们只需要指定一个包扫描的路径,就可以实现更改包扫描路径的功能了。
1.ComponentScan注解扫描包
@ComponentScan({"com.company.user","com.company.service"})
2.ComponentScan注解扫描类。
@ComponentScan(basePackageClasses={XxxService.class})
三.ComponentScan注解
ComponentScan注解中定义了12个属性,我们下面详细来看一下。
我们的讨论是基于java8的,spring-context的版本是4.3.7。
1.String[] value() default {};
指定包扫描路径,value属性的值,就是项目中的一个具体路径。
value属性的类型是String数组,也就是支持一次指定多个包扫描路径。
这个属性上面添加了一个注解,@AliasFor("basePackages"),这个注解的意思就是说,value这个属性等价于basePackages属性。
关于basePackages属性,下面会讲到。
2.String[] basePackages() default {};
指定包扫描路径,basePackages属性的值,就是项目中的一个具体路径。
- basePackages属性的类型是String数组,也就是支持一次指定多个包扫描路径。
- basePackages属性上面添加了一个注解,@AliasFor("value"),这个注解的意思就是说,basePackages这个属性等价于value属性。
3.Class<?>[] basePackagesClasses() default {};
扫描具体的类。
basePackagesClasses属性的类型是Class数组,也就是说支持同时指定多个扫描类。
4,Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator. class;
配置beanName生成器,默认是BeanNameGenerator。
一般情况下,我们都是使用默认的beanName生成器,但是Spring实现了beanName生成器的可配置。
5,Class<? extends ScopeMetaDataResolver> scopeResolver() default AnnotationScopeMetaDataResolver.class;
处理检测到的bean的scope范围。
什么意思呢?
我们都知道spring的bean是有作用域的,默认是singleton,这个默认值就是在ScopeMetaData类中指定的:
private String scopeName = "singleton";
这个属性也是可选配置,默认的处理bean作用域的实现类是AnnotationScopeMetaDataResolver.class。
源码比较简单,就是取注解上获取指定的scope的value值,如果没有配置,就是用默认的singleton。
6.ScopedProxyMode scopedProxy() default ScopedProxyMode. DEFAULT;
是否为检测到的组件生产代理。
ScopedProxyMode是一个枚举类,可选值有四个:
DEFAULT
NO
INTERFACES
TARGET_CLASS
7.String resourcePattern() default """**/*.class";
控制符合组件检测条件的类文件,默认是包扫描下的 **/*.class。
8.boolean useDefaultFilters() default true;
是否对含有以下注解的类开启检测,默认是开启的。
@Component
@Repository
@Service
@Controller
9.ComponentScan.Filter[] includeFilters() default {};
指定某些Filter扫描到的类。听起来有些费劲,说白了就是指定了类型,扫描指定的这些类型。
可选类型有5种,定义在枚举类FilterType中:
- 第一种:ANNOTATION
- 第二种:ASSIGNABLE_TYPE
- 第三种:ASPECTJ
- 第四种:REGEX,正则表达式。
- 第五种:CUSTOM,自定义类型。
10.ComponentScan.Filter[] excludeFilters() default {};
排除过滤器扫描的的类。
11.boolean lazyInit() default false;
扫描到的类是否开启懒加载,默认不开启。
12.
@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 {}; }
ComponentScan的内部接口,主要是对Filter的封装。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。