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全部生效。

@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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决Springboot @WebFilter拦截器未生效问题

    问题描述 @WebFilter(filterName = "ssoFilter",urlPatterns = "/*") 未生效拦截器 解决方法 在springboot启动类上添加 @ServletComponentScan(basePackages = "full.package.path") 路径替换为@WebFilter所在包 补充知识:在spring boot中使用@WebFilter配置filter(包括排除URL) 我就废话不多说了,

  • springboot Interceptor拦截器excludePathPatterns忽略失效

    springboot Interceptor拦截器excludePathPatterns忽略失效 excludePathPatterns方法是排除访问路径,但是当你排除的url路径在项目中并不存在的时候,springboot会将路径编程/error,从而无法进行排除. 例如下面代码: registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login&q

  • 解决SpringBoot自定义拦截器和跨域配置冲突的问题

    目录 SpringBoot自定义拦截器和跨域配置冲突 技术栈 问题引出 原代码 新代码 SpringBoot 拦截器和addCorsMappings冲突 SpringBoot自定义拦截器和跨域配置冲突 技术栈 vue-cli3,springboot 2.3.2.RELEASE 问题引出 在做毕业设计过程中用到了自定义拦截器验证登录.同时在springboot配置类中设置了跨域问题,出现跨域失败的情况. 原代码 @Configuration public class WebConfig exten

  • springboot自动配置没有生效的问题定位(条件断点)

    Spring Boot在为开发人员提供更高层次的封装,进而提高开发效率的同时,也为出现问题时如何进行定位带来了一定复杂性与难度.但Spring Boot同时又提供了一些诊断工具来辅助开发与分析,如spring-boot-starter-actuator.本文分享一个基于actuator与IDEA条件断点来定位自动配置未生效的案例.望对类似问题分析与处理提供参考. 问题确认 在前文介绍的 Spring Boot从入门到实战:整合通用Mapper简化单表操作 中,我们对druid连接池做了自动配置,

  • SpringBoot @CompentScan excludeFilters配置无效的解决方案

    目录 @CompentScan excludeFilters配置无效 FilterType @ComponentScan excludeFilters 自定义过滤器 一.@ComponentScan的作用 二.定义组件 三.在主程序类中测试 四.@ComponentScan中excludeFilters使用 @CompentScan excludeFilters配置无效 @CompentScan 注解配置需要扫描的包 excludeFilters 是其中一个配置项,用于排除不需要扫描的类 Fil

  • Springboot 跨域配置无效及接口访问报错的解决方法

    跨域配置如下,Springboot 版本为 2.4.1 ///跨域访问配置 @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowCredentials(true); //sessionid 多次访问一致 co

  • Mybatis-Plus 全局配置无效的解决方案

    目录 全局配置无效 Mybatis-plus简单配置及应用 mybatis-plus条件构造 mybatis generator条件构造 全局配置无效 依赖         <dependency>             <groupId>com.baomidou</groupId>             <artifactId>mybatis-plus-boot-starter</artifactId>             <ve

  • SpringBoot之@Value获取application.properties配置无效的解决

    目录 @Value获取application.properties配置无效问题 @Value获取application.properties中的配置取值为Null 解决方法 正确做法 总结 @Value获取application.properties配置无效问题 无效的原因主要是要注意@Value使用的注意事项: 1.不能作用于静态变量(static): 2.不能作用于常量(final); 3.不能在非注册的类中使用(需使用@Componet.@Configuration等): 4.使用有这个属

  • Springboot mybatis plus druid多数据源解决方案 dynamic-datasource的使用详解

    依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>p6spy</groupId>

  • springboot参数传中文乱码的解决方案

    前言 本文案例来自业务部门的一个业务场景.他们的业务场景是他们部门研发了一个微服务上下文透传组件,其透传原理也挺简单的,就是通过springboot拦截器把请求参数塞进threadlocal,然后下游通过threadlocal取到值,服务之间进行feign调用时,再把threadlocal的参数塞到header头里面.这个组件一直用得好好的,突然有一天因为传的参数值是中文,导致乱码.他们通过尝试下面的各种方案,都无法解决.最后就让我们部门排查处理. 业务部门的实现思路 他们一开始的思路方向是参数

  • SpringBoot对Druid配置SQL监控功能失效问题及解决方法

    由于我使用的是properties类型的配置文件,在对druid的参数进行配置的时候,多加了druid,也就是spring.datasource.druid.xxx,运行sql语句后SQL监控功能无效. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/userinfo?useUnicode=true&characterEnc

  • 解决springboot中@DynamicUpdate注解无效的问题

    springboot 中 @DynamicUpdate 注解无效解决方案 遇到的问题 项目中使用 jpa,以前没用过,所以踩坑在所难免. 在使用过程中,要更新一条记录的某个字段,更新成功以后,发现整条记录只剩下我更新的那个字段,其他的全部为空了. 瞬间明白,这种更新是全覆盖,针对每个字段 update,实体类没赋值的字段,也直接将空值 set 过去了. 寻求解决方案 正在庆幸这么容易就解决,突然发现并没有这么简单. 群众的力量是无穷大的,我立刻就明白这个注解为什么无效,原来是搞错了它的用途. 一

  • SpringBoot整合Apollo配置中心快速使用详解

    目录 一.简介 二.使用 1. 测试项目搭建 2. Apollo配置中心的配置 3. 项目启动与测试 4.常见整合问题 附录 一.简介 1.Apollo 是什么?Apollo(阿波罗)是携程框架部门研发的分布式配置中心.服务端基于Spring Boot和Spring Cloud开发. 2.为什么要使用Apollo? 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏 时效性:普通方式配置,修改配置,需要重启服务才能生效 局限性:无法支持动态调整:例如日志开关.功能开关 二.使用 1. 测试项

  • springboot html调用js无效400问题及解决

    目录 springboot html调用js无效400 例如 无法访问css,js,图片等静态资源的三种方案 第一种解决方法 第二种解决方法 第三种解决方法 springboot html调用js无效400 html板在templates下面,js文件在static下面,在模板中引用时不需要加static这个路径. 例如 src   └─main      ├─java      └─resources          ├─static          │  ├─css          │

随机推荐