Como verificar vários caminhos usando a anotação @ComponentScan?

90

Estou usando o Spring 3.1 e inicializando um aplicativo usando os atributos @Configuratione @ComponentScan.

O início real é feito com

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Esta classe de configuração é anotada com

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

e isso funciona bem. No entanto, gostaria de ser mais específico sobre os pacotes que escaneio e tentei.

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

No entanto, isso falha com erros informando que não é possível encontrar os componentes especificados usando a @Componentanotação.

Qual é a maneira correta de fazer o que procuro?

obrigado

Cara de programação
fonte
Duas respostas corretas dadas quase ao mesmo tempo, pelo que posso dizer. Vou aceitar o hage só porque ele tem menos pontos, mas agradeço a ambos.
Programming Guy
Se você está se perguntando a mesma coisa para a versão kotlin, verifique este stackoverflow.com/a/62818187/7747942
Sylhare

Respostas:

161

@ComponentScan usa array de string, como este:

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

Quando você fornece vários nomes de pacote em apenas uma string, o Spring interpreta isso como um nome de pacote e, portanto, não pode encontrá-lo.

hage
fonte
48

Há outra alternativa segura de tipo para especificar um local de pacote básico como uma String. Veja a API aqui , mas também ilustrei abaixo:

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

Usar o especificador basePackageClasses com suas referências de classe dirá ao Spring para escanear esses pacotes (assim como as alternativas mencionadas ), mas este método é seguro para tipos e adiciona suporte IDE para refatoração futura - uma grande vantagem em meu livro.

Lendo a partir da API, Spring sugere a criação de uma classe de marcador no-op ou interface em cada pacote que você deseja verificar, que não serve a nenhum outro propósito além de ser usada como uma referência para / por este atributo.

IMO, eu não gosto das classes de marcador (mas, novamente, elas são muito parecidas com as classes de informações do pacote), mas o tipo de segurança, suporte a IDE e redução drástica do número de pacotes básicos necessários para incluir nesta varredura é, sem dúvida, uma opção muito melhor.

Prancer
fonte
Alguém poderia explicar por que @ComponentScan ({"com.app", "com.controllers"}) não funciona para mim, mas @ComponentScan (basePackageClasses = {"com.controllers"}) funciona bem? Acho chato escrever o nome de cada classe
xaverras
3
Você só precisa especificar uma classe no pacote, para o pacote que deseja escanear. Isso é conhecido como classe de marcador. Se você precisa escanear um pacote superior na hierarquia que não tem classes, spring sugere uma técnica usando uma interface de "marcador de mola" ou classe final definida naquele pacote apenas para fins de escaneamento de pacote.
Prancer de
17

Forneça o nome do seu pacote separadamente, ele requer um String[]para os nomes dos pacotes.

Em vez disso:

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

Usa isto:

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

Outra maneira de fazer isso é usando o basePackagescampo; que é um campo dentro da anotação ComponentScan.

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

Se você olhar para a anotação ComponentScan .class do arquivo jar, você verá um campo basePackages que leva em uma matriz de Strings

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

Ou você pode mencionar as classes explicitamente. Que tem uma variedade de classes

Class<?>[]  basePackageClasses
shashwatZing
fonte
4

Você usa o ComponentScan para digitalizar vários pacotes usando

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

ksw
fonte
1

certifique-se de ter adicionado esta dependência em seu pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Amirtha Krishnan
fonte
Obrigado, depois de passar quase meia hora, esta era a dependência que faltava
DvixExtract
1

Você também pode usar a anotação @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
fonte
4
Considere adicionar explicações à sua resposta
yeya
1

Eu uso:

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