从@ComponentScan中排除@Component

时间:2013-09-24 22:03:28

标签: java spring dependency-injection spring-boot spring-ioc

我想要从特定@ComponentScan的{​​{1}}中排除某个组件:

@Configuration

否则,它似乎与我项目中的其他类冲突。我并不完全理解碰撞,但如果我注释掉@Component("foo") class Foo { ... } 注释,那么事情就像我想要的那样。但是依赖这个库的其他项目希望这个类由Spring管理,所以我想只在我的项目中跳过它。

我尝试使用@Component

@ComponentScan.Filter

但它似乎不起作用。如果我尝试使用@Configuration @EnableSpringConfigured @ComponentScan(basePackages = {"com.example"}, excludeFilters={ @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) public class MySpringConfiguration {} ,我会因为无法加载一些看似随机的类而得到一个奇怪的错误:

  

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

我还尝试使用FilterType.ASSIGNABLE_TYPE,如下所示:

type=FilterType.CUSTOM

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

如何排除它?

7 个答案:

答案 0 :(得分:77)

配置似乎没问题,除了您应该使用excludeFilters而不是excludes

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

答案 1 :(得分:39)

在扫描过滤器中使用显式类型对我来说很难看。我相信更优雅的方法是创建自己的标记注释:

public @interface IgnoreDuringScan {
}

标记应该用它排除的组件:

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

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

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

答案 2 :(得分:22)

另一种方法是使用新的条件注释。 从 plain 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

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

答案 3 :(得分:9)

如果您需要定义两个或更多 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) })

答案 4 :(得分:7)

在尝试排除特定配置类时,使用 @Configuration @EnableAutoConfiguration @ComponentScan 时出现问题,问题是它没用!

最终我使用@SpringBootApplication解决了这个问题,根据Spring文档,它在一个注释中执行与上述三个相同的功能。

另一个提示是首先尝试不进行包扫描(不使用basePackages过滤器)。

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

答案 5 :(得分:1)

如果排除测试组件或测试配置,Spring Boot 1.4引入了新的测试注释@TestComponent and @TestConfiguration

答案 6 :(得分:0)

我需要从应用程序上下文中排除审核@Aspect @Component,但仅适用于一些测试类。我最终在方面类上使用@Profile(“ audit”);包括正常操作的配置文件,但不包括特定测试类的配置文件(不要将其放在@Act​​iveProfiles中)。