SpringBoot @CompentScan excludeFilters配置无效的解决方案
作者:LoWang 发布时间:2022-08-01 09:06:42
@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全部生效。
@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的实例
package info.pigg.study.java.service;
import org.springframework.stereotype.Service;
@Service("myBeanService")
public class MyService {
}
2. @Configuration+@Bean
MyConfig 类被扫描后,会生成名为myBeanPerson和myBeanUser两个实例
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”)
@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指向类名
@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注解的类
@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方法中可以获取当前扫描到的类的信息,比如注解、类名和类路径。
@SpringBootApplication
@ComponentScan(value = "info.pigg.study.java", excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})})
public class DictApplication {
}
下面举例:在类名包含"MyService"时,match方法返回true,这样在excludeFilters时,包含"MyService"的类就会被排除掉。
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


猜你喜欢
- 一. 泛型概念的提出(为什么需要泛型)?首先,我们看下下面这段简短的代码:public class GenericTest {public
- 设计模式分类:创建型模式。结构型模式。行为模式。23种设计模式,如何记。面向对象的系统中有很多对象,创建型模式解决的问题就是如何创建对象,何
- 本文实现了C#隐式运行CMD命令的功能。下图是实例程序的主画面。在命令文本框输入DOS命令,点击“Run”按钮,在下面的文本框中输出运行结果
- 背景某项目,客户要求使用已有的 weblogic 部署已经开发好的 springboot,于是乎对 springboot 进行了部分配置的调
- 一、封装一个工具类1、简易版package net.aexit.construct.acceptance.websky.utils;impo
- Mybatis selectKey返回新增用户的id值一、需求:新增用户后,同时还要返回当前新增用户的id值id是由数据库的自动增长来实现的
- 本文实例讲述了Java实现求数组最长子序列算法。分享给大家供大家参考,具体如下:问题:给定一个长度为N的数组,找出一个最长的单调自增子序列(
- 前言Bitmap相信对各位Android开发者们来说都不陌生,用它可以获取图片信息,进行图片剪切、平移、旋转、缩放等操作,并可以指定格式保存
- 对于网站的安全性,是每个网站开发者和运营者最关心的问题。网站一旦出现漏洞,那势必将造成很大的损失。为了提高网站的安全性,首先网站要防注入,最
- CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。
- 本文实例讲述了Java HashMap三种循环遍历方式及其性能对比。分享给大家供大家参考,具体如下:HashMap的三种遍历方式(1)for
- Java8被称作Java史上变化最大的一个版本。其中包含很多重要的新特性,最核心的就是增加了Lambda表达式和StreamAPI。这两者也
- 文章描述可能我标题描述不太准确,所以还是要稍微解释下:横线样式就是将TextBox以一条底横线的形式展示在页面,占位提示就是Web的Plac
- 没有用Java写过程序,做为一个Java新手,在写第一个Hello,world程序之前,先在Ubuntu中搭建Java开发环境。一、JDK安
- 本文实例讲述了C#异步委托调用实现方法。分享给大家供大家参考。具体如下:static void Main(string[] args){ /
- 项目中很多时候需要读取自定义配置文件,本地开发工具怎么写都成功但是部署到服务其上就出现问题,异常BOOT-INF/classes!/conf
- 效果图激活引擎第一步配置APP_ID和SDK_KEY int activeCode = FaceEngine.activeOnline( C
- 异步方法很好的解决了这些问题,异步执行某个方法,程序立即开辟一个新线程去运行你的方法,主线程包括界面就不会死掉了。异步如何开始,好理解,现在
- 一、堆参数设置-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志-XX:+UseSerialGC 配置串行回收器
- 从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘