your type test scan example defining context consider componentscan component bean basepackages array java spring dependency-injection spring-boot spring-ioc

java - type - spring boot component scan controller



excluir @Component de @ComponentScan (7)

En caso de excluir el componente de prueba o la configuración de prueba, Spring Boot 1.4 introdujo nuevas anotaciones de prueba @TestComponent y @TestConfiguration .

Tengo un componente que quiero excluir de @ComponentScan en una @Configuration particular:

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

De lo contrario, parece chocar con alguna otra clase en mi proyecto. No entiendo completamente la colisión, pero si hago un comentario sobre la anotación @Component , las cosas funcionan como yo quiero. Pero otros proyectos que dependen de esta biblioteca esperan que esta clase sea administrada por Spring, por lo que quiero omitirla solo en mi proyecto.

Intenté usar @ComponentScan.Filter :

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

pero no parece funcionar. Si intento utilizar FilterType.ASSIGNABLE_TYPE , FilterType.ASSIGNABLE_TYPE un extraño error acerca de no poder cargar una clase aparentemente aleatoria:

Causado por: java.io.FileNotFoundException: class path resource [junit / framework / TestCase.class] no se puede abrir porque no existe

También intenté usar type=FilterType.CUSTOM siguiente manera:

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

Pero eso no parece excluir el componente del escaneo como yo quiero.

¿Cómo lo excluyo?


En caso de que necesite definir dos o más criterios de excludeFilters , debe usar la matriz.

Para instancias en esta sección de código, deseo excluir todas las clases en el paquete org.xxx.yyy y otra clase específica, MyClassToExclude

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


La configuración parece correcta, excepto que debe usar excludeFilters lugar de excludes :

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


Necesitaba excluir una auditoría @Aspect @Component del contexto de la aplicación, pero solo para unas pocas clases de prueba. Terminé usando @Profile ("auditoría") en la clase de aspecto; incluyendo el perfil para operaciones normales pero excluyéndolo (no lo pongas en @ActiveProfiles) en las clases de prueba específicas.


Otro enfoque es usar nuevas anotaciones condicionales. Desde plain Spring 4 puedes usar @Conditional Annotation:

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

y define la lógica condicional para registrar el componente Foo:

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

La lógica condicional se puede basar en el contexto, porque tiene acceso a la fábrica de bean. Por ejemplo, cuando el componente "Barra" no está registrado como bean:

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

Con Spring Boot (debe usarse para CADA nuevo proyecto de Spring), puede usar estas anotaciones condicionales:

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

Puede evitar la creación de clase de condición de esta manera. Consulte los documentos Spring Boot para obtener más detalles.


Tuve un problema al usar @Configuration , @EnableAutoConfiguration y @ComponentScan al tratar de excluir clases de configuración específicas, ¡la cosa es que no funcionó!

Eventualmente resolví el problema usando @SpringBootApplication , que según la documentación de Spring tiene la misma funcionalidad que las tres de arriba en una anotación.

Otro consejo es probar primero sin refinar el escaneo de su paquete (sin el filtro basePackages).

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


Usar tipos explícitos en los filtros de escaneo es feo para mí. Creo que un enfoque más elegante es crear una propia anotación de marcador:

public @interface IgnoreDuringScan { }

Marque el componente que debe excluirse con él:

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

Y excluya esta anotación del análisis de componentes:

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