Spring 启动 ComponentScan excludeFIlters 不排除
Spring boot ComponentScan excludeFIlters not excluding
我有一个 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 class
package application.starters;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Starter {
@PostConstruct
public void init(){
System.out.println("initializing");
}
}
应用程序 class 看起来像这样:
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 class 仍在初始化。
任何人都可以解释为什么 ComponentScan excludeFilters
不排除我的 Starter
class 吗?
每个组件扫描单独进行过滤。当您从 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 将使用该模拟而不是真正的 class,因此不会调用 @PostConstruct
方法。
其他常见解决方案:
- 不要在任何单元测试中直接使用
Application.class
- 在
Starter
class 上使用 Spring 配置文件和注释,例如 @Profile("!TEST")
- 在
Starter
class 上使用 spring 引导 @ConditionalOn...
注释
您可以定义自定义组件扫描过滤器以排除它。
示例代码如下:
@SpringBootApplication()
@ComponentScan(excludeFilters=@Filter(type = FilterType.REGEX, pattern="com.wyn.applications.starter.Starter*"))
public class SimpleTestConfig {
}
这对我有用。
如需进一步阅读,请转至此 blog。
我有一个 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 class
package application.starters;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Starter {
@PostConstruct
public void init(){
System.out.println("initializing");
}
}
应用程序 class 看起来像这样:
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 class 仍在初始化。
任何人都可以解释为什么 ComponentScan excludeFilters
不排除我的 Starter
class 吗?
每个组件扫描单独进行过滤。当您从 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 将使用该模拟而不是真正的 class,因此不会调用 @PostConstruct
方法。
其他常见解决方案:
- 不要在任何单元测试中直接使用
Application.class
- 在
Starter
class 上使用 Spring 配置文件和注释,例如 - 在
Starter
class 上使用 spring 引导
@Profile("!TEST")
@ConditionalOn...
注释
您可以定义自定义组件扫描过滤器以排除它。
示例代码如下:
@SpringBootApplication()
@ComponentScan(excludeFilters=@Filter(type = FilterType.REGEX, pattern="com.wyn.applications.starter.Starter*"))
public class SimpleTestConfig {
}
这对我有用。
如需进一步阅读,请转至此 blog。