¿Excluir los subpaquetes del cableado automático Spring?

82

¿Existe una forma sencilla de excluir un paquete / subpaquete del cableado automático en Spring 3.1?

Por ejemplo, si quisiera incluir un escaneo de componentes con un paquete base de, com.example¿existe una forma sencilla de excluirlo com.example.ignore?

(¿Por qué? Me gustaría excluir algunos componentes de mis pruebas de integración)

HolySamosa
fuente

Respuestas:

84

No estoy seguro de que pueda excluir paquetes explícitamente con un <exclude-filter>, pero apuesto a que usar un filtro de expresiones regulares lo llevaría efectivamente allí:

 <context:component-scan base-package="com.example">
    <context:exclude-filter type="regex" expression="com\.example\.ignore\..*"/>
 </context:component-scan>

Para que esté basado en anotaciones, anotaría cada clase que desea excluir para las pruebas de integración con algo como @ com.example.annotation.ExcludedFromITests. Entonces el escaneo de componentes se vería así:

 <context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" expression="com.example.annotation.ExcludedFromITests"/>
 </context:component-scan>

Eso es más claro porque ahora ha documentado en el propio código fuente que la clase no está destinada a incluirse en un contexto de aplicación para pruebas de integración.

Jonathan W
fuente
El uso del filtro de exclusión funciona, pero no tuve que escapar "."
Amin
2
@Amin Eso es probablemente porque "." representa cualquier carácter, incluido el literal "."
aksh1618
54

Estoy usando @ComponentScanlo siguiente para el mismo caso de uso. Es lo mismo que la respuesta XML de BenSchro10, pero utiliza anotaciones. Ambos usan un filtro contype=AspectJ

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.example" },
    excludeFilters = @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = "com.example.ignore.*"))
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Kirby
fuente
Tal vez sea pura nostalgia, pero en realidad prefiero XML todavía
Kirby
10
puede que sea yo, pero con Spring 4.2 tengo que usar FilterType.REGEXpara este enfoque
ThanksForAllTheFish
Esto era lo que quería, pero también tenía que usar FilterType.REGEX. ¿Quizás la respuesta podría actualizarse para reflejar esto?
Adam
1
Siéntase libre de hacer una nueva respuesta
Kirby
37

Para Spring 4 utilizo lo siguiente
(lo estoy publicando ya que la pregunta tiene 4 años y más personas usan Spring 4 que Spring 3.1):

@Configuration
@ComponentScan(basePackages = "com.example", 
  excludeFilters = @Filter(type=FilterType.REGEX,pattern="com\\.example\\.ignore\\..*")) 
public class RootConfig {
    // ...
}
Witold Kaczurba
fuente
13

Parece que ha hecho esto a través de XML, pero si estuviera trabajando en la nueva práctica recomendada de Spring, su configuración estaría en Java, y podría excluirlos como tal:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.example.tool",
  excludeFilters = {@ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE,
    value = {JPAConfiguration.class, SecurityConfig.class})
  })
Arsalan Khalid
fuente
9
@JonathanW Pero, sin embargo, una respuesta realmente útil para las personas que llegan a esta página desde una búsqueda en Google
Stewart
12

Esto funciona en Spring 3.0.5. Entonces, creo que funcionaría en 3.1

<context:component-scan base-package="com.example">  
    <context:exclude-filter type="aspectj" expression="com.example.dontscanme.*" />  
</context:component-scan> 
BenSchro10
fuente
1
Tenga en cuenta que ignora silenciosamente la exclusión en caso de que el aspecto no esté presente en classpath.
Vadzim
7

Creo que debería refactorizar sus paquetes en una jerarquía más conveniente, para que estén fuera del paquete base.

Pero si no puede hacer esto, intente:

<context:component-scan base-package="com.example">
    ...
    <context:exclude-filter type="regex" expression="com\.example\.ignore.*"/>
</context:component-scan>

Aquí puede encontrar más ejemplos: Uso de filtros para personalizar el escaneo

richarbernal
fuente
Gracias, en principio estoy de acuerdo con la idea de refactorizar, fue mi primer pensamiento. Desafortunadamente, no es una gran opción para mi situación particular.
HolySamosa
Un buen diseño de paquete puede evitar estas situaciones, pero si no puede ... no puede jajaja :)
richarbernal
4

Una cosa que parece funcionar para mí es esta:

@ComponentScan(basePackageClasses = {SomeTypeInYourPackage.class}, resourcePattern = "*.class")

O en XML:

<context:component-scan base-package="com.example" resource-pattern="*.class"/>

Esto anula el predeterminado resourcePatternque es "**/*.class".

Esta parecería ser la forma más segura de incluir SOLAMENTE su paquete base, ya que resourcePattern siempre será el mismo y relativo a su paquete base.

leeor
fuente
2

También puede usar @SpringBootApplication , que según la documentación de Spring hace la misma funcionalidad que las siguientes tres anotaciones: @Configuration , @EnableAutoConfiguration @ComponentScan en una anotación.

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}
Dorony
fuente
Según Javadoc, excludees excluir clases específicas de configuración automática , no todas las clases del análisis de componentes. Si lo intenta, obtendrá un error " Las siguientes clases no se pudieron excluir porque no son clases de configuración automática ".
Abhijit Sarkar
0

También puede incluir un paquete específico y excluirlos como:

Incluir y excluir (ambos)

 @SpringBootApplication
        (
                scanBasePackages = {
                        "com.package1",
                        "com.package2"
                },
                exclude = {org.springframework.boot.sample.class}
        )

SÓLO excluir

@SpringBootApplication(exclude= {com.package1.class})
public class MySpringConfiguration {}
Rishabh Agarwal
fuente
Según Javadoc, excludees excluir clases específicas de configuración automática , no todas las clases del análisis de componentes. Si lo intenta, obtendrá un error " Las siguientes clases no se pudieron excluir porque no son clases de configuración automática ".
Abhijit Sarkar