欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-15 10:32:45
目录@compentscan excludefilters配置无效filtertype@componentscan excludefilters 自定义过滤器一、@componentscan的作用二、...

@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

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