exclude @Component from @ComponentScan
The configuration seem alright, except that you should use excludeFilters
instead of excludes
:
@Configuration @EnableSpringConfigured@ComponentScan(basePackages = {"com.example"}, excludeFilters={ @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})public class MySpringConfiguration {}
Using explicit types in scan filters is ugly for me. I believe more elegant approach is to create own marker annotation:
@Retention(RetentionPolicy.RUNTIME)public @interface IgnoreDuringScan {}
Mark component that should be excluded with it:
@Component("foo") @IgnoreDuringScanclass Foo { ...}
And exclude this annotation from your component scan:
@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class))public class MySpringConfiguration {}
Another approach is to use new conditional annotations.Since plain Spring 4 you can use @Conditional annotation:
@Component("foo")@Conditional(FooCondition.class)class Foo { ...}
and define conditional logic for registering Foo component:
public class FooCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // return [your conditional logic] } }
Conditional logic can be based on context, because you have access to bean factory. For Example when "Bar" component is not registered as bean:
return !context.getBeanFactory().containsBean(Bar.class.getSimpleName());
With Spring Boot (should be used for EVERY new Spring project), you can use these conditional annotations:
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnJava
@ConditionalOnMissingBean
@ConditionalOnMissingClass
@ConditionalOnNotWebApplication
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication
You can avoid Condition class creation this way. Refer to Spring Boot docs for more detail.