代码之家  ›  专栏  ›  技术社区  ›  Daniel Taub

弹簧防尘套组件扫描排除过滤器不排除

  •  18
  • Daniel Taub  · 技术社区  · 6 年前

    我有一个 简单测试 :

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

    和a 配置 对于本测试:

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

    我试图排除 开胃菜

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

    以及 应用 类如下所示:

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

    但出于一个非常奇怪的原因 开胃菜 类仍在初始化。

    谁能解释一下为什么 ComponentScan excludeFilters 不排除我的 Starter

    2 回复  |  直到 6 年前
        1
  •  27
  •   tkruse    5 年前

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

    一种方法是提供一个模拟 开胃菜 bean:

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

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

    其他常见解决方案:

    • 请勿直接使用 Application.class 在任何单元测试中
    • 使用弹簧轮廓和注释,例如 @Profile("!TEST") 开胃菜
    • 使用弹簧防尘套 @ConditionalOn... 上的注释 开胃菜
        2
  •  3
  •   Ilya Serbis    4 年前

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

    示例代码如下:

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

    这对我有用。

    要进一步阅读,请访问此 blog .