@ComponentScan注解的排除属性
@ComponentScan
组件源码,直截取了用到的属性:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
// 是否使用默认过滤规则:默认为true,被@Component、@Repository、@Service、@Controller锁修饰的组件都会被加入到IOC容器
boolean useDefaultFilters() default true;
// 被包含的过滤器集合
Filter[] includeFilters() default {};
// 被排除的过滤器集合
Filter[] excludeFilters() default {};
/** 过滤器 */
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
// 过滤类型:默认为注解类型
FilterType type() default FilterType.ANNOTATION;
// 需要过滤的类型
@AliasFor("classes")
Class<?>[] value() default {};
// 需要过滤的类型
@AliasFor("value")
Class<?>[] classes() default {};
// 过滤规则
String[] pattern() default {};
}
}
/** 过滤类型 */
public enum FilterType {
// 注解
ANNOTATION,
// 类
ASSIGNABLE_TYPE,
// AOP
ASPECTJ,
// 正则
REGEX,
// 自定义
CUSTOM
}
我们所需要了解到的核心就是spring
加载bean组件
时,采用的是一个什么策略,我怎么控制spring
加载某个bean组件
,反之,我又怎么控制spring
不加载某个bean组件
,下面这个类中的registerDefaultFilters()
方法就是用来接收我们设定的过滤规则集合的:
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
/** 注册默认的过滤规则集合 */
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
}
/** 添加需要包含的组件 */
public void addIncludeFilter(TypeFilter includeFilter) {
this.includeFilters.add(includeFilter);
}
/** 添加需要过滤的组件 */
public void addExcludeFilter(TypeFilter excludeFilter) {
this.excludeFilters.add(0, excludeFilter);
}
到这里,其实我们已经搞懂了spring
的默认的过滤规则了,那么如果我们需要排除某个类型的组件该如何操作?过滤组件的原理是在bean
组件结果集中排除指定的组件。
useDefaultFilters属性的含义
useDefaultFilters
属性用来指定是否按照spring
默认的规则加载bean
组件,如果该属性的值为【false】,那么被@Component
、@Repository
、@Service
、@Controller
所修饰的组件都不会被加入到IOC容器,看到这你应该就明白了,一旦你不按照spring
默认的规则加载bean
组件,那么你就必须使用includeFilters
属性指定需要加入到IOC
容器的bean
组件,否则IOC
容器就是空的。
总结
1、如果需要排除某个组件,只需要指定excludeFilters
属性即可
2、一旦不按照spring
默认的规则加载bean
组件,则必须使用includeFilters
属性指定需要加入到IOC
容器的bean
组件