Spring Boot的ComponentScan excludeFilters无法排除。

9 浏览
0 Comments

Spring Boot的ComponentScan excludeFilters无法排除。

我有一个SimpleTest:\n

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

\n和一个配置SimpleTestConfig的测试:\n

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

\n我试图排除Starter类:\n

package application.starters;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Starter {
    @PostConstruct
    public void init(){
        System.out.println("initializing");
    }
}

\n而Application类如下所示:\n

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

\n但是出于某种奇怪的原因,Starter类仍然被初始化。\n有谁能解释为什么ComponentScan excludeFilters没有排除我的Starter类吗?

0
0 Comments

在使用Spring Boot时,有时候我们需要排除某些组件或类不被自动扫描到。Spring Boot提供了@ComponentScan注解来控制组件的扫描范围,通过设置excludeFilters属性可以指定需要排除的组件。

然而,在一些情况下,excludeFilters属性可能无法正常工作,即使设置了过滤器也无法排除指定的组件。这个问题的出现可能是由于配置不正确或者其他未知原因导致的。

解决这个问题的方法是自定义组件扫描过滤器来排除指定的组件。通过设置excludeFilters属性的值为自定义的过滤器类型和正则表达式模式,可以实现对指定组件的排除。

以下是一个示例代码,展示了如何使用自定义过滤器来排除指定组件:

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

在这个示例中,我们使用了正则表达式过滤器(FilterType.REGEX)来匹配以"com.wyn.applications.starter.Starter"开头的类名,并将其排除在组件扫描范围之外。

通过这种方式,我们可以自定义排除指定组件的规则,从而解决Spring Boot中@ComponentScan excludeFilters属性无法正常工作的问题。

如果想进一步了解更多关于Spring Boot中组件扫描的内容,可以参考这篇博客文章

0
0 Comments

问题出现的原因是每个组件扫描都是独立进行过滤的。尽管在SimpleTestConfig中排除了Starter.class,但SimpleTestConfig初始化了Application,它会进行自己的扫描而不排除Starter

解决方法是使用ComponentScan的正确方式是为每个ComponentScan扫描不同的包,这样每个过滤器都能正常工作。当两个独立的ComponentScan扫描相同的包(如你的测试中)时,这种方法不起作用。

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

import org.springframework.boot.test.mock.mockito.MockBean;
public class SimpleTest {
    private Starter myTestBean;
    ...
}

Spring将使用该模拟类而不是真正的类,这样componentScan方法就不会被调用。

其他常见的解决方法包括:

- 在任何单元测试中不直接使用Application.class

- 在Starter类上使用Spring profile和注解,如@Profile("!TEST")

- 在Starter类上使用Spring Boot的@ComponentScan注解

感谢您的回答,但如果是这样的话,Spring为什么设计了过滤器?它的目的是什么?

过滤器的目的是为了让您灵活地使用。当一个testConfig进行组件扫描时,可以排除另一个配置,而该配置对相似的包进行了自己的组件扫描(就像你的情况中的Application一样),这时过滤器就非常有用。

另一个选项是使用@ComponentScan.Filter注解,详情请参考:stackoverflow.com/a/59815772/355438。请随意修改我的答案以包含该选项。

0