4. @ComponentScan 注解

490 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

1. 注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
// 表示 @Component 注解是一个重复可用的注解
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

Filter[] includeFilters() default {};

Filter[] excludeFilters() default {};

@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {

// 类型:默认情况下,值为 ANNOTATION 注解
FilterType type() default FilterType.ANNOTATION;
}

@Component 注解中其中存在两个方法:

  • includeFilters 表示 spring 按照一定的规则扫描某些需要包含的组件
  • excludeFilters 表示 spring 按照一定的规则扫描某些不需要包含的组件

上面两个方法类型都是 Filter[] 数组,而Filter是一个内部注解类

1.1 测试

使用 excludeFilters :

@ComponentScan(value = {"com.shanggushenlong"},
excludeFilters = {@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
@Configuration
public class MainBeanConfig {

@Bean(value = {"person01"})
public Person person() {
return new Person("张三", 28);
}
}

excludeFilters 排除type 类型为 Annotation 的 类型,Controller Service

如果排除了成功,那么只剩下 Respoitory dao

image (11).png

现在只剩下 dao, Controller 与 Sevice 已经被排除掉了,所以无法被扫描到

使用 includeFilters:扫描时只扫描包含某些注解的类

注:当使用 includeFilters 的时候,必需要禁用掉默认的过滤规则

在 xml 配置文件中,禁用掉默认的过滤规则

<context:component-scan base-package="com.shanggushenlong" use-default-filters="false"></context:component-scan>

使用默认属性 use-default-filters=false

使用 @ComponentScan 注解的时候,使用 useDefaultFilters = false

//@ComponentScan(value = {"com.shanggushenlong"}, excludeFilters = {
// @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})})
@ComponentScan(value = {"com.shanggushenlong"},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})},
useDefaultFilters = false)
@Configuration
public class MainBeanConfig {

@Bean(value = {"person01"})
public Person person() {
return new Person("张三", 28);
}
}

现在只扫描 Controller.class ,容器中只存在 Controller

image (12).png

2、可重复使用注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
... ...
}

@Repeatable(ComponentScans.class) 表示这是一个可重复使用的注解,可以在一个类中使用多次

ComponentScans 类如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {

// 数组,表示可以有多个 ComponentScan
ComponentScan[] value();

}

那现在在配置类中重复使用 @ComponentScan 试试


// 让 spring 扫描含有 @Controller 注解的类
@ComponentScan(value = {"com.shanggushenlong"},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})},
useDefaultFilters = false)
// 让 spring 扫描含有 @Service 注解的类
@ComponentScan(value = {"com.shanggushenlong"},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})},
useDefaultFilters = false)
@Configuration
public class MainBeanConfig {

@Bean(value = {"person01"})
public Person person() {
return new Person("张三", 28);
}
}

image (13).png 现在容器中不仅仅有 Controller,还有 Service

注意:type=FilterType.ANNOTATION type 表示定义扫描的规则类型, ANNOTATION 表示是按照注解类型扫描

FilterType 类如下:

public enum FilterType {

// 表示类型是按照注解规则过滤
ANNOTATION,

ASSIGNABLE_TYPE,

//
ASPECTJ,

// 按照正则表达式扫描过滤
REGEX,

// 用户自定义规则过滤
CUSTOM
}

3.4 @ComponentScans 注解

重复注解使用要求是 JDK8 已以上才能用,若在此之前想要使用多个则可以使用 @ComponentScans,这是一个数组,表示里面可以设置多个 @ComponentScan 注解,具体格式如下:

@ComponentScans(value = {
@ComponentScan(value = {"com.shanggushenlong"}, includeFilters = {@ComponentScan.Filter()}),
@ComponentScan(value = {"com.shanggushenlong"}, includeFilters = {@ComponentScan.Filter()})
})
@Configuration
public class MainBeanConfig {
... ...
}

3 总结

  • xml 文件配置扫描 <context:component-scan base-package="com.shanggushenlong">
  • 如果不是 xml 配置文件,使用注解 @ComponentScan 用于类注解, @ComponentScan(value = {"com.shanggushenlong"}) ,其中 value 值是扫描路径,数组,可以配置多个路径值
  • @ComponentScan 方法: includeFilters excludeFilters 两个方法都是 Filter 数组类型 , includeFilters 表示扫描包含哪些,excludeFilters 表示扫描不包含排除哪些;
  • Filter 也是一个注解,@Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), 其中 type 表示扫描过滤的类型,有注解 正则表达式 用户自定义 等多种类型
  • @ComponentScan 注解是在一个类上可多次重复使用的注解
  • @ComponentScans 可设置多个 @ComponentScan