¿Cómo escanear múltiples rutas usando la anotación @ComponentScan?

89

Estoy usando Spring 3.1 y arrancando una aplicación usando los atributos @Configurationy @ComponentScan.

El inicio real se realiza con

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Esta clase de configuración está anotada con

@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass

y esto funciona bien. Sin embargo, me gustaría ser más específico sobre los paquetes que escaneo, así que lo intenté.

@Configuration
@ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass

Sin embargo, esto falla con errores que me dicen que no puede encontrar los componentes especificados usando la @Componentanotación.

¿Cuál es la forma correcta de hacer lo que busco?

Gracias

Chico de programación
fuente
Dos respuestas correctas dadas aproximadamente al mismo tiempo, por lo que yo sé. Daré el visto bueno a Hage solo porque tiene menos puntos, pero gracias a ambos.
Programming Guy
Si se está preguntando lo mismo para la versión de kotlin , consulte este stackoverflow.com/a/62818187/7747942
Sylhare

Respuestas:

159

@ComponentScan usa una matriz de cadenas, como esta:

@ComponentScan({"com.my.package.first","com.my.package.second"})

Cuando proporciona varios nombres de paquetes en una sola cadena, Spring lo interpreta como un nombre de paquete y, por lo tanto, no puede encontrarlo.

hage
fuente
48

Existe otra alternativa de tipo seguro para especificar la ubicación de un paquete base como String. Vea la API aquí , pero también he ilustrado a continuación:

@ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})

El uso del especificador basePackageClasses con las referencias de su clase le dirá a Spring que escanee esos paquetes (al igual que las alternativas mencionadas ), pero este método es seguro para los tipos y agrega soporte IDE para refactorizaciones futuras, una gran ventaja en mi libro.

Al leer de la API, Spring sugiere crear una clase o interfaz de marcador no operativo en cada paquete que desea escanear que no tenga otro propósito que ser utilizado como referencia para este atributo.

En mi opinión, no me gustan las clases de marcadores (pero, de nuevo, son casi como las clases de información de paquetes), sino la seguridad de tipos, el soporte IDE y la reducción drástica de la cantidad de paquetes básicos necesarios para incluir en este escaneo. es, sin lugar a dudas, una opción mucho mejor.

Prancer
fuente
¿Alguien podría explicar por qué @ComponentScan ({"com.app", "com.controllers"}) no funciona para mí pero @ComponentScan (basePackageClasses = {"com.controllers"}) funciona bien? Me parece aburrido escribir el nombre de cada clase
xaverras
3
Solo tiene que especificar una clase en el paquete, para el paquete que desea escanear. Esto se conoce como clase de marcador. Si necesita escanear un paquete más alto en la jerarquía que no tiene clases, Spring sugiere una técnica que usa una interfaz de "marcador de resorte" o una clase final definida en ese paquete únicamente con el propósito de escanear el paquete.
Prancer
17

Proporcione el nombre de su paquete por separado, requiere un String[]nombre de paquete.

En lugar de esto:

@ComponentScan("com.my.package.first,com.my.package.second")

Utilizar esta:

@ComponentScan({"com.my.package.first","com.my.package.second"})
mprabhat
fuente
10

Otra forma de hacer esto es usando el basePackagescampo; que es un campo dentro de la anotación ComponentScan.

@ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})

Si observa el .class de anotación ComponentScan del archivo jar, verá un campo basePackages que incluye una matriz de cadenas

public @interface ComponentScan {
String[] basePackages() default {};
}

O puede mencionar las clases explícitamente. Que toma una variedad de clases

Class<?>[]  basePackageClasses
shashwatZing
fuente
4

Utiliza ComponentScan para escanear múltiples paquetes usando

@ComponentScan({"com.my.package.first","com.my.package.second"})

ksw
fuente
1

asegúrese de haber agregado esta dependencia en su pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Amirtha Krishnan
fuente
Gracias después de pasar cerca de media hora, esta era la dependencia que faltaba
DvixExtract
1

Yo suelo:

@ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
Yann
fuente
0

También puede usar la anotación @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
fuente
4
Considere agregar una explicación a su respuesta
yeya