java Spring boot ComponentScan excludeFIlters 不排除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48102883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:58:09  来源:igfitidea点击:

Spring boot ComponentScan excludeFIlters not excluding

javaspringspring-bootspring-test

提问by Daniel Taub

I am having a SimpleTest:

我有一个SimpleTest

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SimpleTestConfig.class)
public class SimpleTest {
    @Test
    public void test() {
        assertThat(true);
    }
}

and a configurationfor this test :

以及此测试的配置

@SpringBootApplication
@ComponentScan(basePackageClasses = {
        SimpleTestConfig.class,
        Application.class
},
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = Starter.class))
public class SimpleTestConfig {
}

I am trying to exclude the Starterclass

我正在尝试排除Starter

package application.starters;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
public class Starter {
    @PostConstruct
    public void init(){
        System.out.println("initializing");
    }
}

And the Applicationclass looks like this :

应用类如下所示:

package application;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import static org.springframework.boot.SpringApplication.run;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        run(Application.class, args);
    }
}

But for a very weird reason the Starterclass is still getting initialized.

但是出于一个非常奇怪的原因,Starter类仍在初始化。

Can anyone explain why the ComponentScan excludeFiltersis not excluding my Starterclass ?

谁能解释为什么ComponentScan excludeFilters不排除我的Starter班级?

回答by tkruse

Each component scan does filtering individually. While you exclude Starter.classfrom SimpleTestConfig, SimpleTestConfiginitializes Application, which does it's own @ComponentScanwithout excluding Starter. The clean way of using ComponentScan is for each ComponentScan to scan separate packages, that way each filter works fine. When 2 separate ComponentScans scan the same package (as in your tests), this does not work.

每个组件扫描单独进行过滤。当您排除Starter.classfrom 时SimpleTestConfigSimpleTestConfiginitializes Application,它在@ComponentScan不排除的情况下是自己的Starter。使用 ComponentScan 的干净方式是让每个 ComponentScan 扫描单独的包,这样每个过滤器都可以正常工作。当 2 个单独的 ComponentScans 扫描同一个包时(如在您的测试中),这不起作用。

One way to trick this is to provide a mock Starterbean:

解决这个问题的一种方法是提供一个模拟Starterbean:

import org.springframework.boot.test.mock.mockito.MockBean;

public class SimpleTest {
    @MockBean
    private Starter myTestBean;
    ...
}

Spring will use that mock instead of the real class, thus the @PostConstructmethod will not be called.

Spring 将使用该模拟而不是真正的类,因此@PostConstruct不会调用该方法。

Other common solutions:

其他常见解决方案:

  • Do not directly use Application.classin any unit test
  • Use Spring profile and annotations such as @Profile("!TEST")on the Starterclass
  • Use a spring Boot @ConditionalOn...annotation on the Starterclass
  • 不要Application.class在任何单元测试中直接使用
  • @Profile("!TEST")Starter类上使用 Spring 配置文件和注释
  • @ConditionalOn...Starter类上使用 spring Boot注释

回答by Yogi

You can define custom component scan filter for excluding it.

您可以定义自定义组件扫描过滤器以排除它。

Example code will be like:

示例代码将类似于:

@SpringBootApplication()
@ComponentScan(excludeFilters=@Filter(type = FilterType.REGEX, pattern="com.wyn.applications.starter.Starter*"))
public class SimpleTestConfig {

}

This works for me.

这对我有用。

For further reading go to this blog.

如需进一步阅读,请访问此博客

回答by dorony

@SpringBootApplication, according to Spring documentation does the combined functionality of: @Configuration, @EnableAutoConfigurationand @ComponentScanin one notation.

@SpringBootApplication,根据 Spring 文档,在一种符号中组合了以下功能: @Configuration@EnableAutoConfiguration@ComponentScan

Try first without refining your package scan (without the basePackages filter).

首先尝试不优化您的包扫描(没有 basePackages 过滤器)。

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}