Spring注解[email protected]、@Bean、@ComponentScan的过滤规则FilterType详解
程序员文章站
2022-05-21 22:38:07
...
@Configuration和@Bean
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:@Configuration注解的配置类有如下要求:
- @Configuration不可以是final类型;
- @Configuration不可以是匿名类;
- 嵌套的configuration必须是静态类。
//@Configuration告诉Spring这是一个配置类
@Configuration
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
@Bean
public Person person(){
return new Person("zhangsan", 18);
}
}
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = (Person) ac.getBean("person");
System.out.println(person);
//获取person的类型
String[] beanNamesForType = ac.getBeanNamesForType(Person.class);
for(String name: beanNamesForType){
System.out.println(name);
}
}
}
Person{name='zhangsan', age=18}
person
@ComponentScan
-
basePackages与value: 用于指定包的路径,进行扫描
-
basePackageClasses: 用于指定某个类的包的路径进行扫描
-
nameGenerator: bean的名称的生成器
-
useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
-
includeFilters: 包含的过滤条件
- FilterType.ANNOTATION:按照注解过滤
- FilterType.ASSIGNABLE_TYPE:按照给定的类型
- FilterType.ASPECTJ:使用ASPECTJ表达式
- FilterType.REGEX:正则
- FilterType.CUSTOM:自定义规则
-
excludeFilters: 排除的过滤条件,用法和includeFilters一样
示例:
在容器中注册Controller、service和dao
package pers.zhang.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import pers.zhang.bean.Person;
//@Configuration告诉Spring这是一个配置类
@Configuration
@ComponentScan(value = "pers.zhang")//开启扫描
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
@Bean
public Person person(){
return new Person("zhangsan", 18);
}
}
测试:
@Test
public void test01(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = ac.getBeanDefinitionNames();
for(String name : definitionNames){
System.out.println(name);
}
}
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDao
bookService
person
使用excludeFilters和includeFilters过滤扫描
Filter中type的类型
- ANNOTATION:注解类型
- ASSIGNABLE_TYPE:指定的类型
- ASPECTJ:按照Aspectj的表达式,基本上不会用到
- REGEX:按照正则表达式
- CUSTOM:自定义规则
@ComponentScan(value = "pers.zhang", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})//开启扫描
//过滤掉Controller和Service注解的Bean
//excludeFilters参数为Filter数组,type为过滤规则
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookDao
person
@ComponentScan(value = "pers.zhang", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, useDefaultFilters = false)//开启扫描
//过滤:只包含Controller
//useDefaultFilters默认为true,改为false
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
person
通过类型指定过滤规则:
@ComponentScan(value = "pers.zhang", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})
}, useDefaultFilters = false)//开启扫描
//所有BookService类型(包括子类)都在扫描的时候添加为Bean
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookService //被扫描进来
person
自定义过滤规则
写一个TypeFilter的实现类:
package pers.zhang.config;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
public class MyTypeFilter implements TypeFilter {
@Override //MetadataReader:当前正在扫描的类的信息; MetadataReaderFactory:可以获取到其它任何类信息
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);
//类名不包含er,则注册为Bean
if(!className.contains("er")){
return true;
}
return false;
}
}
@ComponentScan(value = "pers.zhang", 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)//开启扫描