Srping注解 @ComponentScan
1.创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的
<context:component-scan>。
2.使用 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}),
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcludeMyAnnotation.class})
},
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {IncludeMyAnnotation.class}),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE , classes = {Person2.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}
, useDefaultFilters = false
)
}
)
public class BeanConfig {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IncludeMyAnnotation {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeMyAnnotation {
}
public class MyTypeFilter implements TypeFilter {
@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;
}
}
@IncludeMyAnnotation
public class Person1 {
}
@ExcludeMyAnnotation
@Component
public class Person2 {
}
public class Person3 {
}
优先级
自定义的@ComponentScan优先级大于@SpringBootApplication默认的,要注意的是,
自定义的@ComponentScan的路径一定要包含启动类项目路径,默认为配置类所在的路径
注意
1.自定义@ComponentScan时注意控制的路径范围
2.有重名的Bean会注册失败
问题!!!
1.spring 有默认的规律规则 会对 @Component、@ManagedBean、@Named注解的Bean进行扫描,如果设置了
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class})
但是加了@service的类依然被注册到ioc
所以要设置 useDefaultFilters = false
但是!!!
我这样设置,加了@Service的类还是被注册到Ioc,原因找了半天没找到,希望有了解的人可以解答疑问,谢谢