SpringBoot @CompentScan excludeFilters配置无效的解决方案
这篇文章主要介绍了SpringBoot @CompentScan excludeFilters配置无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
目录
@CompentScan excludeFilters配置无效
FilterType
@ComponentScan excludeFilters 自定义过滤器
一、@ComponentScan的作用
二、定义组件
三、在主程序类中测试
四、@ComponentScan中excludeFilters使用
@CompentScan excludeFilters配置无效
@CompentScan 注解配置需要扫描的包
excludeFilters 是其中一个配置项,用于排除不需要扫描的类
FilterType
ANNOTATION
:根据注解来排除ASSIGNABLE_TYPE
:根据类类型来排除ASPECTJ
:根据AspectJ表达式来排除REGEX
:根据正则表达式来排除CUSTOM
:自定义FilterClass排除,需要实现org.springframework.core.type.filter.TypeFilter接口
在我们项目中,有一个core的module,里面存放了每个项目公用的package,但是有些开发人员把一些无关的初始化操作也放到了core项目中,这就导致如果A项目引用了core,那么就会做一些无用的初始化操作,由于core的子包太多,无法一个一个引用,所以使用排除法是最快的,使用REGEX进行排除操作,但是经过多次尝试,排除的类依然被spring扫描并初始化了,难道是没有效果?经过多方搜索,在这篇文章中得到启发。
Each component scan does filtering individually. While you exclude Starter.class from SimpleTestConfig, SimpleTestConfig initializes Application, which does it's own @ComponentScan without excluding Starter. The clean way of using ComponentScan is for each ComponentScan to scan separate packages, that way each filter work fine. When 2 separate ComponentScans scan the same package (as in your tests), this does not work.
每个组件扫描都会单独进行过滤 当您从SimpleTestConfig中排除Starter.class时,SimpleTestConfig会初始化Application,它会自行执行@ComponentScan而不会排除Starter。 使用ComponentScan的简洁方法是每个ComponentScan扫描单独的包,这样每个过滤器都可以正常工作。 当2个单独的ComponentScans扫描同一个包时(如在测试中),这将不起作用。
大致的意思就是说,如果你在A类中,使用了exlucde配置,在你不需要排除的类中,有某些类B的注解上也使用了@ComponentScan,但是这个类B上注解中没有进行exclude操作,那么你在A类中的exclude将不会生效。结果扫描一下core包下面的类,确实有一个类B使用@ComponentScan,那么在A类中,同时也排除类B,A类中的exclude全部生效。
1 2 3 4 5 6 | @ComponentScan ( basePackages = { "com.scio.core" }, excludeFilters = { @Filter (type = FilterType.REGEX, pattern = "com\\.scio\\.core\\.B" ), @Filter (type = FilterType.REGEX, pattern = "com\\.scio\\.core\\.message\\..*" ) }) |
@ComponentScan excludeFilters 自定义过滤器
一、@ComponentScan的作用
@ComponentScan用于类或接口上,主要是指定扫描路径并把带有指定注解的类注册到Spring容器中。
会被自动装配的注解包括@Component、@Bean、@Controller、@Service、@Repository等等。
二、定义组件
1. @Service注解的类
MyService类被扫描后,会生成名为myBeanService的实例
1 2 3 4 5 | package info.pigg.study.java.service; import org.springframework.stereotype.Service; @Service ( "myBeanService" ) public class MyService { } |
2. @Configuration+@Bean
MyConfig 类被扫描后,会生成名为myBeanPerson和myBeanUser两个实例
1 2 3 4 5 6 7 8 9 10 11 12 | package info.pigg.study.java.config; @Configuration public class MyConfig { @Bean (name = "myBeanPerson" ) public Person myBeanPerson(){ return new Person( "king" , 31 ); } @Bean (name = "myBeanUser" ) public User myBeanUser(){ return new User( "king" , 31 ); } } |
三、在主程序类中测试
上面定义的组件都属于"info.pigg.study.java",所以添加@ComponentScan(value = “info.pigg.study.java”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @SpringBootApplication @ComponentScan (value = "info.pigg.study.java" ) public class DictApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(DictApplication. class , args); String[] names = run.getBeanDefinitionNames(); //打印出名称包含myBean的实例 for (String name : names) { if (name.contains( "myBean" )) { System.out.println(name); } } } } |
测试结果如下:
myBeanService
myBeanPerson
myBeanUser
四、@ComponentScan中excludeFilters使用
在@ComponentScan可以设置includeFilters和excludeFilters,来自定义过滤器。一般excludeFilters用的比较多。
1. 过滤指定的类名
type = FilterType.ASSIGNABLE_TYPE是根据类class来过滤,后面classes指向类名
1 2 3 4 5 6 | @SpringBootApplication @ComponentScan (value = "info.pigg.study.java" , excludeFilters = { @ComponentScan .Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {MyService. class })}) public class DictApplication { //和上面一样,省略 } |
测试结果如下:
myBeanPerson
myBeanUser
2. 过滤指定的注解
在"info.pigg.study.java"包和子包下,排除有@Service注解的类
1 2 3 4 5 | @SpringBootApplication @ComponentScan (value = "info.pigg.study.java" , excludeFilters = { @ComponentScan .Filter(type = FilterType.ANNOTATION, classes = {Service. class })}) public class DictApplication { } |
测试结果如下:
myBeanPerson
myBea
3. 自定义过滤
type = FilterType.CUSTOM,是自定义过滤,classes 指定的类要实现TypeFilter接口,在match方法中可以获取当前扫描到的类的信息,比如注解、类名和类路径。
1 2 3 4 5 | @SpringBootApplication @ComponentScan (value = "info.pigg.study.java" , excludeFilters = { @ComponentScan .Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter. class })}) public class DictApplication { } |
下面举例:在类名包含"MyService"时,match方法返回true,这样在excludeFilters时,包含"MyService"的类就会被排除掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package info.pigg.study.java.filter; 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 public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前类资源(类的路径) Resource resource = metadataReader.getResource(); ClassMetadata classMetadata = metadataReader.getClassMetadata(); System.out.println( "当前正在被扫描的类的类名" + classMetadata.getClassName()); if (classMetadata.getClassName().contains( "MyService" )){ return true ; } return false ; } } |
测试结果如下:
myBeanPerson
myBea
以上为个人经验,希望能给大家一个参考
原文链接:https://www.jianshu.com/p/2cabfb1975c7