Estou aprendendo a Primavera 3 e não pareço entender a funcionalidade por trás <context:annotation-config>
e <context:component-scan>
.
Pelo que tenho lido eles parecem lidar com diferentes anotações ( @Required
, @Autowired
etc vs @Component
, @Repository
, @Service
etc), mas também pelo que tenho lido que registam os mesmos pós-processador de feijão classes.
Para me confundir ainda mais, existe um annotation-config
atributo on <context:component-scan>
.
Alguém pode lançar alguma luz sobre essas tags? O que é semelhante, o que é diferente, um é substituído pelo outro, eles se completam, eu preciso de um deles, ambos?
java
spring
configuration
annotations
spring-3
user938214097
fonte
fonte
component-scan
sempre que possível.Respostas:
<context:annotation-config>
é usado para ativar anotações em beans já registrados no contexto do aplicativo (não importa se eles foram definidos com XML ou pela varredura de pacote).<context:component-scan>
também pode fazer o que<context:annotation-config>
faz, mas<context:component-scan>
também verifica os pacotes para localizar e registrar beans no contexto do aplicativo.Vou usar alguns exemplos para mostrar as diferenças / semelhanças.
Permite começar com uma configuração básica de três grãos de tipo
A
,B
eC
, comB
eC
ser injectadoA
.Com a seguinte configuração XML:
Carregar o contexto produz a seguinte saída:
OK, esta é a saída esperada. Mas este é o "estilo antigo" da primavera. Agora temos anotações, então vamos usá-las para simplificar o XML.
Primeiro, vamos autorizar as propriedades
bbb
eccc
no bean da seguinteA
maneira:Isso permite remover as seguintes linhas do XML:
Meu XML agora está simplificado para isso:
Quando carrego o contexto, recebo a seguinte saída:
OK, isso está errado! O que aconteceu? Por que minhas propriedades não são conectadas automaticamente?
Bem, as anotações são um recurso interessante, mas elas mesmas não fazem nada. Eles apenas anotam coisas. Você precisa de uma ferramenta de processamento para encontrar as anotações e fazer algo com elas.
<context:annotation-config>
para o resgate. Isso ativa as ações para as anotações encontradas nos beans definidos no mesmo contexto do aplicativo em que ele próprio está definido.Se eu mudar meu XML para isso:
quando carrego o contexto do aplicativo, obtenho o resultado adequado:
OK, isso é legal, mas removi duas linhas do XML e adicionei uma. Essa não é uma grande diferença. A idéia com anotações é que ela deve remover o XML.
Então, vamos remover as definições XML e substituí-las por anotações:
Enquanto no XML, mantemos apenas isso:
Carregamos o contexto e o resultado é ... Nada. Nenhum bean é criado, nenhum bean é conectado automaticamente. Nada!
Isso porque, como eu disse no primeiro parágrafo, o
<context:annotation-config />
único funciona em beans registrados no contexto do aplicativo. Como eu removi a configuração XML dos três beans, ele não é criado e<context:annotation-config />
não possui "destinos" para trabalhar.Mas isso não será um problema para o
<context:component-scan>
qual é possível digitalizar um pacote em busca de "destinos". Vamos mudar o conteúdo da configuração XML para a seguinte entrada:Quando carrego o contexto, recebo a seguinte saída:
Hmmmm ... algo está faltando. Por quê?
Se você olhar de perto para as classes, a classe
A
tem pacote,com.yyy
mas eu especifiquei no<context:component-scan>
pacote para usar,com.xxx
então isso perdeu completamente minhaA
classe e só foi atendidaB
eC
que está nocom.xxx
pacote.Para corrigir isso, adiciono este outro pacote também:
e agora obtemos o resultado esperado:
E é isso! Agora você não tem mais definições XML, possui anotações.
Como exemplo final, mantendo as classes anotadas
A
,B
eC
e adicionando o seguinte ao XML, o que nós vamos ter depois de carregar o contexto?Ainda obtemos o resultado correto:
Mesmo que o bean da classe
A
não seja obtido pela varredura, as ferramentas de processamento ainda serão aplicadas<context:component-scan>
em todos os beans registrados no contexto do aplicativo, mesmo para osA
quais foram registrados manualmente no XML.Mas e se tivermos o XML a seguir, obteremos beans duplicados porque especificamos ambos
<context:annotation-config />
e<context:component-scan>
?Não, sem duplicações, novamente obtemos o resultado esperado:
Isso ocorre porque as duas tags registram as mesmas ferramentas de processamento (
<context:annotation-config />
podem ser omitidas se<context:component-scan>
for especificado), mas o Spring cuida de executá-las apenas uma vez.Mesmo se você registrar as ferramentas de processamento várias vezes, o Spring ainda garantirá que elas façam a mágica apenas uma vez; este XML:
ainda gerará o seguinte resultado:
OK, é sobre o rap.
Espero que essas informações, juntamente com as respostas de @Tomasz Nurkiewicz e @Sean Patrick Floyd, sejam tudo o que você precisa para entender como
<context:annotation-config>
e<context:component-scan>
trabalhar.fonte
Encontrei este belo resumo de quais anotações são captadas por quais declarações. Ao estudá-lo, você descobrirá que
<context:component-scan/>
reconhece um superconjunto de anotações reconhecidas por<context:annotation-config/>
, a saber:@Component
,@Service
,@Repository
,@Controller
,@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
Como você pode ver, estende - se
<context:component-scan/>
logicamente com os recursos de varredura de componente CLASSPATH e Java @Configuration.<context:annotation-config/>
fonte
O Spring permite que você faça duas coisas:
1. Ligação automática
Normalmente, em applicationContext.xml, você define beans e outros beans são conectados usando métodos de construtor ou setter. Você pode conectar beans usando XML ou anotações. No caso de você usar anotações, você precisa anotações ativar e você tem que adicionar
<context:annotation-config />
em applicationContext.xml . Isso simplificará a estrutura da tag em applicationContext.xml , porque você não precisará conectar manualmente beans (construtor ou setter). Você pode usar@Autowire
anotações e os beans serão conectados por tipo.Um passo adiante para escapar da configuração XML manual é
2. Descoberta
Automática A descoberta automática está simplificando o XML um passo adiante, no sentido de que você nem precisa adicionar a
<bean>
tag no applicationContext.xml . Você acabou de marcar os beans específicos com uma das seguintes anotações e o Spring conectará automaticamente os beans marcados e suas dependências no contêiner do Spring. As anotações são as seguintes: @Controller , @Service , @Component , @Repository . Ao usar<context:component-scan>
e apontar o pacote base, o Spring detectará e conectará automaticamente os componentes no contêiner do Spring.Como uma conclusão:
<context:annotation-config />
é usado para poder usar a anotação @Autowired<context:component-scan />
é usado para determinar a pesquisa de beans específicos e a tentativa de fiação automática.fonte
<context:annotation-config>
ativa muitas anotações diferentes nos beans, sejam eles definidos em XML ou por meio da varredura de componentes.<context:component-scan>
é para definir beans sem usar XMLPara mais informações, leia:
fonte
<context:component-scan>
, não poderei substituir a definição de bean usando XML?<context:component-scan>
? Perco algo se não usar o<context:annotation-config>
?A diferença entre os dois é realmente simples!
Permite usar anotações restritas à ligação de propriedades e construtores apenas de beans !.
Enquanto que
Permite que tudo o que
<context:annotation-config />
pode fazer, com adição de usar estereótipos por exemplo ..@Component
,@Service
,@Repository
. Assim, você pode conectar feijões inteiros e não apenas restritos a construtores ou propriedades !.fonte
<context:annotation-config>
: Digitalizando e ativando anotações para beans já registrados no xml de configuração da primavera.<context:component-scan>
: Registro de Bean +<context:annotation-config>
@Autowired e @Required são o nível de propriedade de destinos, portanto, o bean deve se registrar no COI da primavera antes de usar essas anotações. Para ativar essas anotações, é necessário registrar os respectivos beans ou incluir
<context:annotation-config />
. ou seja,<context:annotation-config />
funciona apenas com beans registrados.@Required ativa a
RequiredAnnotationBeanPostProcessor
ferramenta de processamento@Autowired ativa a
AutowiredAnnotationBeanPostProcessor
ferramenta de processamentoNota: A anotação em si não tem nada a ver, precisamos de uma Ferramenta de processamento , que é uma classe abaixo, responsável pelo processo principal.
@Repository, @Service e @Controller são @Component e têm como alvo o nível de classe .
<context:component-scan>
ele verifica o pacote e encontra e registra os beans, além de incluir o trabalho realizado por<context:annotation-config />
.Migrando XML para anotações
fonte
A
<context:annotation-config>
tag diz ao Spring para varrer a base de código para resolver automaticamente os requisitos de dependência das classes que contêm a anotação @Autowired.O Spring 2.5 também adiciona suporte para anotações JSR-250, como @Resource, @PostConstruct e @ PreDestroy. O uso dessas anotações também exige que determinados BeanPostProcessors sejam registrados no contêiner Spring. Como sempre, elas podem ser registradas como definições individuais de bean, mas também podem ser registradas implicitamente, incluindo a
<context:annotation-config>
tag na configuração da mola.Retirado da documentação do Spring da Configuração baseada em anotação
O Spring fornece a capacidade de detectar automaticamente classes 'estereotipadas' e registrar as BeanDefinitions correspondentes no ApplicationContext.
De acordo com javadoc do org.springframework.stereotype :
Estereótipos são anotações que indicam as funções de tipos ou métodos na arquitetura geral (em um nível conceitual, e não de implementação). Exemplo: @Controller @Service @Repository etc. Estes destinam-se ao uso de ferramentas e aspectos (tornando um alvo ideal para pointcuts).
Para detectar automaticamente essas classes de 'estereótipo',
<context:component-scan>
é necessária uma tag.A
<context:component-scan>
tag também diz ao Spring para verificar o código em busca de beans injetáveis sob o pacote (e todos os seus subpacotes) especificados.fonte
Resolve apenas as anotações
@Autowired
e@Qualifer
, isso é tudo, sobre a injeção de dependência . Existem outras anotações que fazem o mesmo trabalho, penso eu@Inject
, mas estão prestes a resolver o DI por meio de anotações.Esteja ciente de que, mesmo quando você declarou o
<context:annotation-config>
elemento, você deve declarar sua classe como um Bean de qualquer maneira, lembre-se de que temos três opções disponíveis<bean>
Agora com
Faz duas coisas:
<context:annotation-config>
faz.Portanto, se você declarar
<context:component-scan>
, não é mais necessário declarar<context:annotation-config>
também.Isso é tudo
Um cenário comum foi, por exemplo, declarar apenas um bean por meio de XML e resolver o DI por meio de anotações, por exemplo
Declaramos apenas os beans, nada sobre
<constructor-arg>
e<property>
, o DI é configurado em suas próprias classes através do @Autowired. Significa que os Serviços usam @Autowired para seus componentes de Repositórios e os Repositórios usam @Autowired para os componentes JdbcTemplate, DataSource etc.fonte
tente com
<context:component-scan base-package="..." annotation-config="false"/>
, na sua configuração @ Service, @ Repository, @ Component funciona bem, mas @ Autowired, @ Resource e @Inject não funcionam.Isso significa que AutowiredAnnotationBeanPostProcessor não será ativado e o contêiner Spring não processará as anotações de ligação automática.
fonte
O outro ponto importante a ser observado é que
context:component-scan
chama implicitamente ocontext:annotation-config
para ativar as anotações nos beans. Bem, se você não desejacontext:component-scan
ativar implicitamente as anotações para você, pode continuar definindo o elemento de anotação-configuração docontext:component-scan
parafalse
.Para resumir:
fonte
<context:component-scan base-package="package name" />
:Isso é usado para informar ao contêiner que existem classes de bean no meu pacote varrer essas classes de bean. Para varrer as classes de bean por contêiner em cima do bean, precisamos escrever uma anotação do tipo estéreo como a seguir.
@Component
,@Service
,@Repository
,@Controller
<context:annotation-config />
:Se não queremos escrever uma tag de bean explicitamente em XML, como o contêiner sabe se há uma fiação automática no bean. Isso é possível usando a
@Autowired
anotação. temos que informar ao contêiner que há fiação automática no meu beancontext:annotation-config
.fonte
Uma
<context:component-scan/>
tag customizada registra o mesmo conjunto de definições de bean que é feito, além de sua principal responsabilidade de varrer os pacotes java e registrar definições de bean no caminho de classe.Se, por algum motivo, esse registro das definições de bean padrão for evitado, a maneira de fazer isso é especificar um atributo "annotation-config" adicional na varredura de componentes, desta maneira:
Referência: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html
fonte
<context:annotation-config>
:Isso diz ao Spring que eu vou usar beans anotados como bean de primavera e eles seriam conectados através da
@Autowired
anotação, em vez de declarar no arquivo xml de configuração do spring.<context:component-scan base-package="com.test...">
:Isso informa ao contêiner do Spring, por onde começar a pesquisar esses beans anotados. Aqui, a primavera pesquisará todos os subpacotes do pacote base.
fonte
você pode encontrar mais informações no arquivo de esquema de contexto da primavera. a seguir está em spring-context-4.3.xsd
fonte
Como complementar, você pode usar
@ComponentScan
para usar<context:component-scan>
em anotações.Também é descrito em spring.io
Uma coisa a observar, se você estiver usando o Spring Boot, o @Configuration e o @ComponentScan podem ser implícitos usando a anotação @SpringBootApplication.
fonte