从@ComponentScan中排除@Component

我有一个组件,我想从一个特定的@Configuration @ComponentScan中排除:

 @Component("foo") class Foo { ... } 

否则,它似乎与我的项目中的其他类冲突。 我不完全理解碰撞,但是如果我注释掉@Component注解,事情就像我想要的那样工作。 但是依赖这个库的其他项目希望这个类由Spring来pipe理,所以我只想在我的项目中跳过它。

我试过使用@ComponentScan.Filter

 @Configuration @EnableSpringConfigured @ComponentScan(basePackages = {"com.example"}, excludeFilters={ @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) public class MySpringConfiguration {} 

但它似乎没有工作。 如果我尝试使用FilterType.ASSIGNABLE_TYPE ,我得到一个奇怪的错误,无法加载一些看似随机的类:

引起:java.io.FileNotFoundException:类path资源[junit / framework / TestCase.class]无法打开,因为它不存在

我也尝试使用type=FilterType.CUSTOM ,如下所示:

 class ExcludeFooFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return metadataReader.getClass() == Foo.class; } } @Configuration @EnableSpringConfigured @ComponentScan(basePackages = {"com.example"}, excludeFilters={ @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) public class MySpringConfiguration {} 

但是,这似乎并不像我想要的那样从扫描中排除组件。

我如何排除它?

configuration看起来没问题,除了你应该使用excludeFilters而不是excludes

 @Configuration @EnableSpringConfigured @ComponentScan(basePackages = {"com.example"}, excludeFilters={ @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) public class MySpringConfiguration {} 

在扫描filter中使用显式types对我来说是丑陋的。 我相信更优雅的方法是创build自己的标记注释:

 public @interface IgnoreDuringScan { } 

标记应该被排除的组件:

 @Component("foo") @IgnoreDuringScan class Foo { ... } 

并从组件扫描中排除此注释:

 @ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class)) public class MySpringConfiguration {} 

另一种方法是使用新的条件注释。 由于普通的 Spring 4你可以使用@Conditional注释:

 @Component("foo") @Conditional(FooCondition.class) class Foo { ... } 

并定义注册Foo组件的条件逻辑:

 public class FooCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // return [your conditional logic] } } 

条件逻辑可以基于上下文,因为你可以访问bean工厂。 例如,当“Bar”组件未注册为bean时:

  return !context.getBeanFactory().containsBean(Bar.class.getSimpleName()); 

使用Spring Boot(应该用于每个新的Spring项目),您可以使用这些条件注释:

  • @ConditionalOnBean
  • @ConditionalOnClass
  • @ConditionalOnExpression
  • @ConditionalOnJava
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnNotWebApplication
  • @ConditionalOnProperty
  • @ConditionalOnResource
  • @ConditionalOnWebApplication

您可以通过这种方式避免创buildCondition类。 有关更多详细信息,请参阅Spring Boot文档。

如果您需要定义两个或更多的excludeFilters标准,则必须使用该数组。

对于这部分代码中的实例,我想排除org.xxx.yyy包中的所有类和另一个特定的类MyClassToExclude

  @ComponentScan( excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.xxx.yyy.*"), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyClassToExclude.class) }) 

在排除testing组件或testingconfiguration的情况下,Spring Boot 1.4引入了新的testing注释@TestComponent@TestConfiguration

我在使用@ Configuration@ EnableAutoConfiguration@ComponentScan的时候遇到了一个问题,试图排除特定的configuration类,事情是不行的!

最后我通过使用@SpringBootApplication解决了这个问题,根据Spring文档,在一个注释中做了与上面三个相同的function。

另一个提示是首先尝试,而不改善你的包扫描(没有basePackagesfilter)。

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