从@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 {}