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


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.


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.


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"})

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

4

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

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


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>

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") })

4
Considere adicionar explicações à sua resposta
yeya

1

Eu uso:

@ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.