【问题标题】:Spring boot ComponentScan excludeFIlters not excludingSpring boot ComponentScan excludeFIlters 不排除
【发布时间】:2018-06-14 15:11:51
【问题描述】:

我正在进行SimpleTest

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

以及此测试的配置

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

我正在尝试排除 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");
    }
}

Application 类看起来像这样:

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);
    }
}

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

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

【问题讨论】:

  • 要么我错过了 SimpleTestConfig 中的主要(方法),要么你没有很好地解释你想从哪里排除
  • 在你的SimpleTestConfig 类上用@Configuration 替换@SpringBootApplication。也希望它在你的 src/main 文件夹中,如果你正在创建一个测试目的配置(在 src/test 文件夹中),请改用@TestConfiguration 注释。

标签: java spring spring-boot spring-test


【解决方案1】:

每个组件扫描都会单独进行过滤。当您从SimpleTestConfig 中排除Starter.class 时,SimpleTestConfig 会初始化Application,这是它自己的@ComponentScan,而不排除Starter。 使用 ComponentScan 的干净方式是让每个 ComponentScan 扫描单独的包,这样每个过滤器都可以正常工作。当 2 个单独的 ComponentScans 扫描同一个包时(就像在您的测试中一样),这不起作用。

一种欺骗方法是提供一个模拟 Starter bean:

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

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

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

其他常见的解决方案:

  • 不要在任何单元测试中直接使用Application.class
  • Starter 类上使用 Spring 配置文件和注释,例如 @Profile("!TEST")
  • Starter 类上使用 spring Boot @ConditionalOn... 注释

【讨论】:

  • 非常感谢您的回答,但如果是这样,那么为什么要在 Spring 中设计过滤器? ,目的是什么?
  • 目的是任何你想要它使用的东西。当 testConfig 执行 componentScan 而不扫描另一个具有它自己的 componentScan 类似包的配置时(例如您的情况下的 Application ),它非常有用。
  • 另一种选择是使用@TypeExcludeFilters注解:stackoverflow.com/a/59815772/355438
  • @Lu55:随意修改我的答案以包含该选项。
【解决方案2】:

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

示例代码如下:

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

}

这对我有用。

如需进一步阅读,请访问blog

【讨论】:

    猜你喜欢
    • 2017-06-10
    • 2014-10-22
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 2015-03-28
    • 2017-07-25
    • 2020-12-21
    • 2016-11-23
    相关资源
    最近更新 更多