前言
之前提到,标注了@Component等注解的类会被注册为Bean。那么@ComponentScan自然就是用于开启包扫描,将Bean注册到Spring IoC环境中的注解。该注解标注在启动类上,它定义了扫描路径,从中找到标识了需要装配的类,自动将其装配到环境中。
在Spring Boot中,我们常常见到的是复合注解
@SpringBootApplication,这个注解的功能之一等效于使用了@ComponentScan,因此我们前面没有显式提到要使用@ComponentScan
源码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default "**/*.class";
boolean useDefaultFilters() default true;
ComponentScan.Filter[] includeFilters() default {};
ComponentScan.Filter[] excludeFilters() default {};
boolean lazyInit() default false;
@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标注在启动类上,如果不传入basePackages属性,那么扫描的路径默认为当前包以及当前路径下的子包,这也是启动类为什么一般放在源代码最外层的原因。
@ComponentScan
public class MyApplication {
// 启动类
}
includeFilters和excludeFilters两个属性的行为比较理解,就是包含或者排除哪些特殊情况,但Filter类值得讲一讲。
FilterType有五种类型:注解类型FilterType.ANNOTATION, 指定固定类FilterType.ASSIGNABLE_TYPE, 切入点类型FilterType.ASPECTJ, 正则表达式FilterType.REGEX, 自定义类型FilterType.CUSTOM
首先说注解类型,比如我们知道@Controller会被注册为Bean,我们可以将其排除。
@ComponentScan(
excludeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class})}
)
public class MyApplication {
// 启动类
}
使用includeFilters将未标注的自定义类注册进容器:
@ComponentScan(
includeFilters={@Filter(type=FilterType.ASSIGNABLE_TYPE, classes={MyClass.class})}
)
public class MyApplication {
// 启动类
}