注解
@ComponentScan 通过此注解来设置包,类的扫描规则。
一、配置文件开发
在 Spring 配置文件中使用 <context:component-scan> 标签来设置包的扫描规则。
二、注解开发
在原来的配置类上面,可以添加 @ComponentScan 注解来添加类的扫描规则。
@ComponentScan 注解中使用 value属性来指定要扫描的包
@Configuration
@ComponentScan(value = "com.njf")//value 指定要扫描的包
public class MainConfig {
/**
* 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person)
* 修改 id 名
* 1)修改方法名;
* 2)注解中 value 值即 bean 的 id
* @return
*/
@Bean(name = "Person")
public Person person01() {
return new Person("李四", 20);
}
}
三、@ComponentScan 常用属性方法
1、指定扫描的包
value() 和 basePackages() 可以指定扫描要的包;
这两个方法都是一样,可以使用 value 或者 basePackages() 来指定扫描的包;(可以使用表达式)
2、排除指定组件
excludeFilters = Filter[] 指定扫描的时候按照指定规则排除那些组件
示例:按照注解规则排除指定的组件
@ComponentScan(value = "com.njf", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
3、包含指定组件
includeFilters = Filter[] 指定扫描的时候按照指定只包含那些组件(把useDefaultFilters设置为false)
示例:按照指定规则扫描对应的组件
@ComponentScan(value = "com.njf", includeFilters = {
@ComponentScan.Filter(type=FilterType.ANNOTATION, classes= {Controller.class}), //使用注解
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}) //使用类的类型
}, useDefaultFilters = false)
注意:默认是扫描所有的组件,一定要禁用掉,然后按照指定的规则扫描,一定要设置 useDefaultFilters 设置为 false,即不扫描全部的,只扫描指定的类。
四、自定义扫描规则
在上面的扫描规则中,都是通过添加 Filter 来指定扫描规则的。
在 @ComponentScan.Filter 注解中有一个 type() 属性方法,指定了通过哪一种规则来进行扫描的。
源码:
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
默认使用的按照注解的类型来扫描的。
FilterType 枚举类中定义了如下几种方式的扫描规则:
FilterType.ANNOTATION 按照注解的类型
FilterType.ASSIGNABLE_TYPE 按照给定的类型
FilterType.ASPECTJ 按照aspectj 表达式
FilterType.REGEX 按照正则表达式来指定
FilterType.CUSTOM 使用自定义规则
可以看到我们可以自定义Filter来进行包的扫描规则。
对于自定义Filter,需要是 TypeFilter 的实现类。
创建自定义的 Filter,定义一个普通类,实现 TypeFilter:
public class MyTypeFilter implements TypeFilter { /* * @param metadataReader : 读取到的当前正在扫描的类的信息 * @param metadataReaderFactory : 可以获取到其他任何类信息 */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的类信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类资源(类的路径) Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println("--->" + className); if (className.contains("er")) { //表示当扫描的类名中有er时,就会包含该类 return true; } return false; } }
使用自定义的过滤规则进行扫描:
@ComponentScan(value = "com.njf", includeFilters = {
@ComponentScan.Filter(type=FilterType.ANNOTATION, classes= {Controller.class}), //使用注解
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), //使用类的类型
@ComponentScan.Filter(type=FilterType.CUSTOM, classes = {MyTypeFilter.class}) //使用自定义规则
}, useDefaultFilters = false)
五、其他
1、@ComponentScan 重复使用
在Spring的高版本(4.0以上)声明为了重复注解:
可以在配置类上写多个 @ComponentScan 扫描规则:
@Configuration @ComponentScan(value = "com.njf", excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) }) @ComponentScan(value = "com.njf", includeFilters = { @ComponentScan.Filter(type=FilterType.ANNOTATION, classes= {Controller.class}), //使用注解 @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), //使用类的类型 @ComponentScan.Filter(type=FilterType.CUSTOM, classes = {MyTypeFilter.class}) //使用自定义规则 }, useDefaultFilters = false) public class MainConfig { /** * 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person) * 修改 id 名 * 1)修改方法名; * 2)注解中 value 值即 bean 的 id * @return */ @Bean(name = "Person") public Person person01() { return new Person("李四", 20); } }
如果是 JDK8,可以像上面写多个包扫描器 @ComponentScan;
如果不是 JDK8,可以使用下面的 @ComponentScans 指定多个包扫描规则;
2、使用@ComponentScans
使用 @ComponentScans 注解,可以在 value 数组里面放多个 @ComponentScan;
@ComponentScans 和 @ComponentScan 注解不可以同时使用!
@Configuration
@ComponentScans(
value = {
@ComponentScan(value = "com.njf", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}),
@ComponentScan(value = "com.njf", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})
})
}
)
public class MainConfig {
/**
* 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person)
* 修改 id 名
* 1)修改方法名;
* 2)注解中 value 值即 bean 的 id
* @return
*/
@Bean(name = "Person")
public Person person01() {
return new Person("李四", 20);
}
}