Spring中的@ComponentScan注解详解
作者:nsnsttn
Spring注解 @ComponentScan
1.添加 @ComponentScan 注解
创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的
<context:component-scan>
2.获取已经注册到容器中的 bean 的名称以及数量
使用 ApplicationContext 的 getBeanDefinitionNames() 方法和getBeanDefinitionCount()获取已经注册到容器中的 bean 的名称以及数量
@SpringBootApplication
public class ZzyNotesApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ZzyNotesApplication.class, args);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
System.out.println("beanName: " + beanName);
}
System.out.println("bean总数:"+context.getBeanDefinitionCount());
}
}
3.@ComponentScan
@SpringBootApplication注解中已经存在,也可以根据需要自定义 @SpringBootApplication(scanBasePackages = "")
常用参数:
1.value || basePackages = "包路径,默认当前类所在包"
2.excludeFilters 使用 excludeFilters 来按照规则排除某些包的扫描。
3.includeFilters 用includeFilters配置 扫描的类
优先级由上之下,比如自定义的MyTypeFilter如果已经Bean已经在ioc容器中,或者上面的excludeFilters已经过滤掉这个Bean,则不扫描这个类
- 参数:
- FilterType.ANNOTATION :注解名规则,Service.class
- FilterType.ASSIGNABLE_TYPE : 按照给定的类型,比如当前类型的父子类。
- FilterType.ASPECTJ :使用aspectj表达式
- FilterType.REGEX :使用正则指定
- FilterType.CUSTOM
4.useDefaultFilters
默认为true ,会优先执行默认的过滤器 对 @Component、@ManagedBean、@Named注解的Bean进行扫描 所以要改为false
配置类代码如下
@Configuration
@ComponentScans(
{
@ComponentScan(value = "com.zzy.zzyNotes" ,useDefaultFilters = false),
@ComponentScan(value = "com.zzy.zzyNotes.spring.createBean",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class}),//排除包含注解Service的类(不生效,原因未知)
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcludeMyAnnotation.class})//排除包含注解MyAnnotation2的类
},
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {IncludeMyAnnotation.class}),//指定扫描包换注解MyAnnotation的类
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),//指定注解扫描包换注解Controller的类
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE , classes = {Person2.class}),//指定类型Person2的类
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})//自定义过滤规则
}
, useDefaultFilters = false//这个没有效果,必须在启动类上的@ComponentScan( useDefaultFilters = false)中配置 false
)
}
)
public class BeanConfig {
}/**
* @author zzy
* @createDate: 2021-12-30 16:26:50
* @description: 自定义注解 指定某个类被扫描
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IncludeMyAnnotation {
}
/**
* @author zzy
* @createDate: 2021-12-30 16:26:50
* @description: 自定义注解 排除某个类被扫描
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeMyAnnotation {
}
/**
* 扫描包自定义规则
* metadataReader:读取到当前正在扫描类的信息
* metadataReaderFactory:可以获取到其他任何类的信息
* 注意:只有不满足其它的规则,才会被自定义过滤规则判断
* @author zzy
*/
public class MyTypeFilter implements TypeFilter {
/**
* @description: 扫描规则
* @params:
* @return: 返回true 加入IOC容器 false ,排除
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前类注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源信息 (比如类存在哪个盘,类的路径 )
Resource resource = metadataReader.getResource();
String name = classMetadata.getClassName();
System.out.println("Filter扫描的类名:" + name);
if(name.contains("Person3")){
return true;
}
return false;
}
}
/**
* @author zzy
* @createDate: 2021-12-30 10:08:35
* @description: 创建Bean Person1 加IncludeMyAnnotation
*/
@IncludeMyAnnotation
public class Person1 {
}
/**
* @author zzy
* @createDate: 2021-12-30 10:10:37
* @description: 创建Bean Person1 加@ExcludeMyAnnotation 被排除
* 正常有@Component就会被扫描,加了@ExcludeMyAnnotation就会被排除
*/
@ExcludeMyAnnotation
@Component
public class Person2 {
}
/**
* @author zzy
* @createDate: 2021-12-30 17:03:44
* @description: 创建Bean Person3 符合MyTypeFilter过滤规则
*/
public class Person3 {
}
其他问题
优先级
- 自定义的@ComponentScan优先级大于@SpringBootApplication默认的,要注意的是,
- 自定义的@ComponentScan的路径一定要包含启动类项目路径,默认为配置类所在的路径
注意
1.自定义@ComponentScan时注意控制的路径范围
2.有重名的Bean会注册失败
问题
spring 有默认的规律规则 会对 @Component、@ManagedBean、@Named注解的Bean进行扫描,如果设置了
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class})
但是加了@service的类依然被注册到ioc
所以要设置 useDefaultFilters = false
到此这篇关于Spring中的@ComponentScan注解详解的文章就介绍到这了,更多相关@ComponentScan注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
