guia itexto: inje Œncias com spring framework 3 … · 2016-01-26 · o objetivo deste guia Ø...
TRANSCRIPT
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
Injeccedilatildeo de Dependecircncias com
Spring Framework 3
O objetivo deste guia eacute expor o
relacionadas ao container de Injeccedilatildeo de Dependecircncias (
Spring Framework 30 O assunto pode interessar o Trata-se do nuacutecleo do Spring Framework sendo assim eacute conhecimento
obrigatoacuterio para todos aqueles que des
Ainda mais importante eacute um padratildeo de projeto que aumenta de forma
significativa a qualidade dos sistemas nos quais eacute aplicado
interesse pelo Spring Framework poderaacute
containeres como Pico miocc ou
Caminhando para a Injeccedilatildeo de DependecircnciasUm projeto de software ruim
fragilidade e imobilidade Fraacutegil
modificaccedilatildeo nos deparamos com efeitos inesperados em outros de seus componentes
rigidez eacute consequumlecircncia desta fragilidadedesenvolvedor vecirc suas opccedilotildees de atuaccedilatildeo limitadas
imobilidade diz respeito agrave dificuldade em se extrair partes do sistema que possam ser
reaproveitadas em outros projetosEstes trecircs problemas possuem
considerado de alto acoplamento quadependentes Por componentes externos ou internos
Para melhor entender o problema um software que busque tiacutetulos de livros escritos por determinado autor
podemos ver sua estrutura inicial
Na classe cliente temos um uacutenico meacutetodo chamado
agrave funccedilatildeo buscaPorAutor da classe DAOLivro que nome do autor passado como paracircmetro
usa como fonte de dados um arquivo Por anos este sistema poderaacute funcionar sem problemas
necessaacuterio usar alguma outra fonte de dPodemos imaginar duas soluccedilotildees que natildeo usem orientaccedilatildeo a objetos para resolver o
problema Na classe DAOLivro
buscaPorAutorNoSGBD que faria a consulta usando um banco de eacute uma soluccedilatildeo interessante pois
incluindo uma nova funccedilatildeo que
funccedilatildeo de buscaPorAutor Tambeacutem podemos alterar a funccedilatildeo
no qual pudeacutessemos definir qual a fontemesmo problema da soluccedilatildeo anterior
Imagem 1 - Nosso modelo inicial
pendecircncias com Spring Framework 3
Injeccedilatildeo de Dependecircncias com
Spring Framework 3
eacute expor o porquecirc como usar e quais as melhores praacuteticas
container de Injeccedilatildeo de Dependecircncias (Dependency Injection ou DI
O assunto pode interessar o leitor pelas seguintes razotildees
se do nuacutecleo do Spring Framework sendo assim eacute conhecimento
obrigatoacuterio para todos aqueles que desejem usaacute-lo ou seus derivados Ainda mais importante eacute um padratildeo de projeto que aumenta de forma
significativa a qualidade dos sistemas nos quais eacute aplicado Mesmo que o leitor natildeo se
interesse pelo Spring Framework poderaacute usaacute-lo em seus trabalhos adotandcomo Pico miocc ou mesmo o seu proacuteprio se for o caso
Injeccedilatildeo de Dependecircncias Um projeto de software ruim costuma apresentar trecircs caracteriacutesticas
Fraacutegil eacute aquele sistema no qual ao se introduzir uma modificaccedilatildeo nos deparamos com efeitos inesperados em outros de seus componentes
desta fragilidade dada a dificuldade em se manter o sistema o desenvolvedor vecirc suas opccedilotildees de atuaccedilatildeo limitadas (ou mesmo anuladas)imobilidade diz respeito agrave dificuldade em se extrair partes do sistema que possam ser
reaproveitadas em outros projetos problemas possuem a mesma causa o alto acoplamento Um sistema eacute
considerado de alto acoplamento quando seus componentes internos satildeo fortemente
dependentes Por componentes devem ser entendidas classes fontes de dados
Para melhor entender o problema vamos usar um exemplo bastante trivial que seraacute
usque tiacutetulos de livros escritos por determinado autor Na imagem 1
podemos ver sua estrutura inicial
Na classe cliente temos um uacutenico meacutetodo chamado buscar() que faz uma chamada da classe DAOLivro que encontra tiacutetulos de livros escritos p
passado como paracircmetro Imaginemos por um momento que DAOLivro usa como fonte de dados um arquivo texto
Por anos este sistema poderaacute funcionar sem problemas Mas e se no futuro fosse outra fonte de dados digamos um banco de dados relacional
Podemos imaginar duas soluccedilotildees que natildeo usem orientaccedilatildeo a objetos para resolver o
Na classe DAOLivro poderiacuteamos criar um novo meacutetodo chamado
que faria a consulta usando um banco de dados relacional Natildeo
eacute uma soluccedilatildeo interessante pois estariacuteamos aumentando a complexidade da classe incluindo uma nova funccedilatildeo que do ponto de vista das classes cliente exerceria a mesma
alterar a funccedilatildeo buscaPorAutor incluindo um novo paracircmetro
definir qual a fonte de dados a ser usada De novo cairiacuteamos
mesmo problema da soluccedilatildeo anterior
Injeccedilatildeo de Dependecircncias com
as melhores praacuteticas
Dependency Injection ou DI) do pelas seguintes razotildees
se do nuacutecleo do Spring Framework sendo assim eacute conhecimento
Ainda mais importante eacute um padratildeo de projeto que aumenta de forma
que o leitor natildeo se
adotando outros
caracteriacutesticas rigidez ao se introduzir uma
modificaccedilatildeo nos deparamos com efeitos inesperados em outros de seus componentes A dada a dificuldade em se manter o sistema o
mo anuladas) Jaacute a
imobilidade diz respeito agrave dificuldade em se extrair partes do sistema que possam ser
alto acoplamento Um sistema eacute
ndo seus componentes internos satildeo fortemente
entendidas classes fontes de dados sistemas
usar um exemplo bastante trivial que seraacute
imagem 1
que faz uma chamada escritos pelo
DAOLivro
Mas e se no futuro fosse ados digamos um banco de dados relacional
Podemos imaginar duas soluccedilotildees que natildeo usem orientaccedilatildeo a objetos para resolver o
criar um novo meacutetodo chamado
dados relacional Natildeo
aumentando a complexidade da classe exerceria a mesma
incluindo um novo paracircmetro
cairiacuteamos no
id4346140 pdfMachine by Broadgun Software - a great PDF writer - a great PDF creator - httpwwwpdfmachinecom httpwwwbroadguncom
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
Dado que estamos lidando com
orientada a objetos uma soluccedilatilde
expotildee um segundo modelo proposto para nosso sistema
O que eacute Padrotildees de Projeto
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
posteriormente adaptado para o desenvolvimento de software orientado a objetoproblemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
comum para todos aqueles que os aplicam Um exemp
O que eacute Padratildeo de Projeto Factory
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
possiacutevel implementaccedilatildeo do padratildeo eacute a que apresentamos
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
classe do sistema venha a ter dependecircncias diretas com todas as implementaccedilotildees presentes de det
ou interface
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da
classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
de IDAOLivro a partir do nome da fonte de dados chamar a funccedilatildeo criarIDAOLivro
interessantes A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo
implementaccedilatildeo especiacutefica Sendo assim agora eacute possiacutevel trabalhar
dados imaginaacutevel desde que implemente a interface IDAOLivro
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
complexidade do sistema
1 O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
Gamma Richard Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
Gangue dos Quatro (Gang of Four ou GoF em inglecircs)
Imagem 2 - Aplicando o padratildeo Factory
pendecircncias com Spring Framework 3
Dado que estamos lidando com a plataforma Java e esta eacute em sua essecircncia
uma soluccedilatildeo mais interessante eacute adotar o padratildeo factory A
um segundo modelo proposto para nosso sistema
Padrotildees de Projeto
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
rmente adaptado para o desenvolvimento de software orientado a objeto1 Trata-se de soluccedilotildees para
problemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
comum para todos aqueles que os aplicam Um exemplo de padratildeo de projeto eacute o Factory descrito neste artigo
Padratildeo de Projeto Factory
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
possiacutevel implementaccedilatildeo do padratildeo eacute a que apresentamos neste artigo cria-se uma classe cujo uacutenico objetivo eacute
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
classe do sistema venha a ter dependecircncias diretas com todas as implementaccedilotildees presentes de determinada classe
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
de IDAOLivro a partir do nome da fonte de dados fornecida pela classe ClientecriarIDAOLivro A soluccedilatildeo adotada apresenta vantagens bastante
A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo
Sendo assim agora eacute possiacutevel trabalhar com qualquer fonte de dados imaginaacutevel desde que implemente a interface IDAOLivro
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
d Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
(Gang of Four ou GoF em inglecircs)
Aplicando o padratildeo Factory
em sua essecircncia adotar o padratildeo factory A imagem 2
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
de soluccedilotildees para
problemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
descrito neste artigo
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
se uma classe cujo uacutenico objetivo eacute
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
erminada classe
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
pela classe Cliente ao A soluccedilatildeo adotada apresenta vantagens bastante
A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo de uma com qualquer fonte de
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
d Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
inversatildeo de dependecircncias cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle
Um moacutedulo de niacutevel mais
pertencente a um niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
contraacuterio Em nosso exemplo a classe
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
IDAOLivro O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo
Observe que as trecircs caracteriacute
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface
classe Cliente Como consequumlecircncia
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda acoplamento da classe Cliente
classe DAOLivro no segundo de apresentar uma terceira versatildeo do sistema cuja ar
A mudanccedila foi sutil apenas explicitamos a presenccedila de um
classe Cliente do tipo IDAOLivro
Cliente3 Agora podemos dizer que atingimos o menor esta classe
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
classe FactoryDAOLivro que possui como dependecircncia tod
presentes no sistema da interface evolua chegaremos a um momento no qual a classe
2 Este beliacutessimo artigo encontra
httpwwwobjectmentorcompublicationsdippd3 Poderiacuteamos tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Imagem 3 - Terceira versatildeo do nosso modelo
pendecircncias com Spring Framework 3
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle2 Este princiacutepio nos diz duas coisas
Um moacutedulo de niacutevel mais alto jamais deve depender diretamente de outro m niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
Em nosso exemplo a classe Cliente eacute um moacutedulo de niacutevel superior natildeo
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo buscaPorAutor
Observe que as trecircs caracteriacutesticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface IDAOLivro natildeo afetaraacute diretamente a
consequumlecircncia o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda estaacute longe do ideal porque aumentamos o Cliente Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
no segundo incluiacutemos outra que eacute a classe FactoryIDAOLivro
de apresentar uma terceira versatildeo do sistema cuja arquitetura eacute exposta na imagem 3
sutil apenas explicitamos a presenccedila de um atributo daoLivro
IDAOLivro cuja instacircncia eacute definida pelo construtor da classe
Agora podemos dizer que atingimos o menor grau de acoplamento possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
que possui como dependecircncia todas as implementaccedilotildees
presentes no sistema da interface IDAOLivro Eacute quase certo que conforme este sistema
evolua chegaremos a um momento no qual a classe FactoryDAOLivro se tornaraacute um
Este beliacutessimo artigo encontra-se acessiacutevel gratuitamente no endereccedilo
httpwwwobjectmentorcompublicationsdippdf tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Terceira versatildeo do nosso modelo
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo The
alto jamais deve depender diretamente de outro
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
eacute um moacutedulo de niacutevel superior natildeo lhe interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual) Jaacute
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta interface mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trata-se da
sticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
natildeo afetaraacute diretamente a
o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar
porque aumentamos o grau de Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
FactoryIDAOLivro Eacute hora
imagem 3
daoLivro na cuja instacircncia eacute definida pelo construtor da classe
possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
as as implementaccedilotildees
Eacute quase certo que conforme este sistema
se tornaraacute um
se acessiacutevel gratuitamente no endereccedilo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
monstro de difiacutecil manutenccedilatildeo A cada nova implementaccedilatildeo de IDAOLivro precisaremos alteraacute-la e compilaacute-la novamente
Aleacutem deste problema temos outro eacute necessaacuteria uma classe que crie uma instacircncia
de Cliente Esta por sua vez possui o mesmo problema apresentado no modelo 2 duas dependecircncias Resumindo chegamos ao limite do que podemos fazer usando apenas o padratildeo Factory
Entra a Injeccedilatildeo de Dependecircncias
A injeccedilatildeo de dependecircncias (Dependency Injection ou DI em inglecircs) eacute uma forma de
inversatildeo de controle na qual o aspecto a ser invertido eacute como o proacuteprio nome jaacute diz a resoluccedilatildeo de dependecircncias Ao inveacutes do desenvolvedor definir manualmente quais as
instacircncias a serem criadas e injetadas como fizemos nos trecircs modelos anteriormente descritos delega-se esta tarefa a um container de inversatildeo de controle (IoC) veja o quadro Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle - evitando assim a necessidade de se implementar o padratildeo factory
Grosso modo podemos pensar no container de IoC como um factory ideal capaz de instanciar qualquer tipo de classe sem que fiquemos presos a uma famiacutelia especiacutefica de
objetos Poreacutem como veremos no caso do Spring este factory vai aleacutem agrave medida que tambeacutem controla o ciclo de vida dos objetos por ele gerenciados Para introduzirmos o conceito imagine que este container eacute uma classe maacutegica que sempre nos retorna um
objeto cujo tipo eacute exatamente aquele que estamos precisando O truque por traacutes desta
maacutegica seraacute exposto no decorrer deste artigo O que eacute uma dependecircncia
Eacute muito raro encontrarmos um software real e uacutetil composto por uma uacutenica classe Na esmagadora maioria das
vezes topamos com classes que possuem atributos cujo tipo satildeo outras classes Estes atributos que referenciam outros
tipos de classe satildeo o que costumamos chamar de dependecircncia
Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle
Se o nuacutecleo do Spring eacute chamado de Container de Inversatildeo de Controle (IoC de Inversion of Control em inglecircs)
porque estamos usando o termo injeccedilatildeo de dependecircncias Porque como bem observou Martin Fowler em seu artigo Inversion of Control Containers and the Dependency Injection Pattern 4 os containeres de inversatildeo de controle
como Spring Pico e outros aplicam um tipo muito especiacutefico de inversatildeo de controle
E neste momento uma segunda pergunta surge o que eacute inversatildeo de controle
Chama-se de inversatildeo de controle a teacutecnica de desenvolvimento na qual um
aspecto comportamental do sistema eacute delegado a uma entidade externa Um exemplo de inversatildeo de controle eacute o EJB O desenvolvedor implementa o
seu EJB e em seguida faz o deploy no servidor de aplicaccedilotildees sem precisar se preocupar com o modo como seu componente seraacute iniciado finalizado e
gerenciado porque neste caso eacute tudo feito pelo servidor Ao inveacutes de nos
preocuparmos com estas tarefas as delegamos a uma entidade externa que normalmente recebe o nome de container
A inversatildeo de controle esta no nuacutecleo do conceito de framework Ao
adotarmos um framework estamos reutilizando a estrutura de uma aplicaccedilatildeo
semi-pronta que finalizamos ao inserir nossos proacuteprios componentes
4 O artigo pode ser online neste endereccedilo httpwwwmartinfowlercomarticlesinjectionhtml
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
customizados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
dependecircncias acabariacuteamos com uma arquitetura similar agrave exposta na
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
FactoryDAOLivro
No novo modelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc
nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
fonte A partir destes dados ecomputacional o container eacute capaz de instanciar
instruamos a fazecirc-lo Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
consequumlecircncia temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees
Caso surja a necessidade de uma nova implementaccedilatildeo
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute
la como um arquivo jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s)necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara
Imagem 4 - Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
pendecircncias com Spring Framework 3
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute delegado
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido portanto que o termo Inversatildeo de Controle
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
com uma arquitetura similar agrave exposta na imagem 4
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das cnosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc-lo a partir de configuraccedilotildees que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
e usando o mecanismo de reflexatildeo provido pelocomputacional o container eacute capaz de instanciar e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees ja a necessidade de uma nova implementaccedilatildeo de alguma das abstraccedilotildees
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute-la jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s) de configuraccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara de ser executada
Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
delegado ao framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Inversatildeo de Controle eacute
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
imagem 4 Observe classes do
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
o ambiente e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolvedor se encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
de alguma das abstraccedilotildees
la distribuiacute-jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
ccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem-se desta maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
Dado que estamos lidando com
orientada a objetos uma soluccedilatilde
expotildee um segundo modelo proposto para nosso sistema
O que eacute Padrotildees de Projeto
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
posteriormente adaptado para o desenvolvimento de software orientado a objetoproblemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
comum para todos aqueles que os aplicam Um exemp
O que eacute Padratildeo de Projeto Factory
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
possiacutevel implementaccedilatildeo do padratildeo eacute a que apresentamos
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
classe do sistema venha a ter dependecircncias diretas com todas as implementaccedilotildees presentes de det
ou interface
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da
classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
de IDAOLivro a partir do nome da fonte de dados chamar a funccedilatildeo criarIDAOLivro
interessantes A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo
implementaccedilatildeo especiacutefica Sendo assim agora eacute possiacutevel trabalhar
dados imaginaacutevel desde que implemente a interface IDAOLivro
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
complexidade do sistema
1 O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
Gamma Richard Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
Gangue dos Quatro (Gang of Four ou GoF em inglecircs)
Imagem 2 - Aplicando o padratildeo Factory
pendecircncias com Spring Framework 3
Dado que estamos lidando com a plataforma Java e esta eacute em sua essecircncia
uma soluccedilatildeo mais interessante eacute adotar o padratildeo factory A
um segundo modelo proposto para nosso sistema
Padrotildees de Projeto
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
rmente adaptado para o desenvolvimento de software orientado a objeto1 Trata-se de soluccedilotildees para
problemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
comum para todos aqueles que os aplicam Um exemplo de padratildeo de projeto eacute o Factory descrito neste artigo
Padratildeo de Projeto Factory
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
possiacutevel implementaccedilatildeo do padratildeo eacute a que apresentamos neste artigo cria-se uma classe cujo uacutenico objetivo eacute
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
classe do sistema venha a ter dependecircncias diretas com todas as implementaccedilotildees presentes de determinada classe
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
de IDAOLivro a partir do nome da fonte de dados fornecida pela classe ClientecriarIDAOLivro A soluccedilatildeo adotada apresenta vantagens bastante
A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo
Sendo assim agora eacute possiacutevel trabalhar com qualquer fonte de dados imaginaacutevel desde que implemente a interface IDAOLivro
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
d Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
(Gang of Four ou GoF em inglecircs)
Aplicando o padratildeo Factory
em sua essecircncia adotar o padratildeo factory A imagem 2
O conceito de padrotildees de projeto foi cunhado por Cristopher Alexander no contexto da arquitetura civil e
de soluccedilotildees para
problemas recorrentes na criaccedilatildeo de software que possuem soluccedilotildees padronizadas e fornecem um vocabulaacuterio em
descrito neste artigo
O padratildeo factory fornece uma interface para criaccedilatildeo de famiacutelias de objetos correlatos ou dependentes Uma
se uma classe cujo uacutenico objetivo eacute
criar novas instacircncias de objetos que implementem determinada interface fazendo com que apenas uma uacutenica
erminada classe
Nesta nova arquitetura a classe Cliente depende agora da interface IDAOLivro e da classe FactoryDAOLivro a segunda responsaacutevel por instanciar a implementaccedilatildeo correta
pela classe Cliente ao A soluccedilatildeo adotada apresenta vantagens bastante
A classe Cliente eacute dependente apenas da interface IDAOLivro e natildeo de uma com qualquer fonte de
A responsabilidade pela instanciaccedilatildeo de objetos que implementem a interface
IDAOLivro fica centralizada em uma uacutenica classe reduzindo significativamente a
O termo se consagrou na disciplina de engenharia de software com o livro Padrotildees de Projeto de Erich
d Helm Ralph Johnson e John Vlissides (os quatro autores tambeacutem satildeo conhecidos como a
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
inversatildeo de dependecircncias cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle
Um moacutedulo de niacutevel mais
pertencente a um niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
contraacuterio Em nosso exemplo a classe
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
IDAOLivro O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo
Observe que as trecircs caracteriacute
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface
classe Cliente Como consequumlecircncia
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda acoplamento da classe Cliente
classe DAOLivro no segundo de apresentar uma terceira versatildeo do sistema cuja ar
A mudanccedila foi sutil apenas explicitamos a presenccedila de um
classe Cliente do tipo IDAOLivro
Cliente3 Agora podemos dizer que atingimos o menor esta classe
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
classe FactoryDAOLivro que possui como dependecircncia tod
presentes no sistema da interface evolua chegaremos a um momento no qual a classe
2 Este beliacutessimo artigo encontra
httpwwwobjectmentorcompublicationsdippd3 Poderiacuteamos tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Imagem 3 - Terceira versatildeo do nosso modelo
pendecircncias com Spring Framework 3
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle2 Este princiacutepio nos diz duas coisas
Um moacutedulo de niacutevel mais alto jamais deve depender diretamente de outro m niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
Em nosso exemplo a classe Cliente eacute um moacutedulo de niacutevel superior natildeo
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo buscaPorAutor
Observe que as trecircs caracteriacutesticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface IDAOLivro natildeo afetaraacute diretamente a
consequumlecircncia o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda estaacute longe do ideal porque aumentamos o Cliente Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
no segundo incluiacutemos outra que eacute a classe FactoryIDAOLivro
de apresentar uma terceira versatildeo do sistema cuja arquitetura eacute exposta na imagem 3
sutil apenas explicitamos a presenccedila de um atributo daoLivro
IDAOLivro cuja instacircncia eacute definida pelo construtor da classe
Agora podemos dizer que atingimos o menor grau de acoplamento possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
que possui como dependecircncia todas as implementaccedilotildees
presentes no sistema da interface IDAOLivro Eacute quase certo que conforme este sistema
evolua chegaremos a um momento no qual a classe FactoryDAOLivro se tornaraacute um
Este beliacutessimo artigo encontra-se acessiacutevel gratuitamente no endereccedilo
httpwwwobjectmentorcompublicationsdippdf tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Terceira versatildeo do nosso modelo
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo The
alto jamais deve depender diretamente de outro
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
eacute um moacutedulo de niacutevel superior natildeo lhe interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual) Jaacute
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta interface mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trata-se da
sticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
natildeo afetaraacute diretamente a
o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar
porque aumentamos o grau de Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
FactoryIDAOLivro Eacute hora
imagem 3
daoLivro na cuja instacircncia eacute definida pelo construtor da classe
possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
as as implementaccedilotildees
Eacute quase certo que conforme este sistema
se tornaraacute um
se acessiacutevel gratuitamente no endereccedilo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
monstro de difiacutecil manutenccedilatildeo A cada nova implementaccedilatildeo de IDAOLivro precisaremos alteraacute-la e compilaacute-la novamente
Aleacutem deste problema temos outro eacute necessaacuteria uma classe que crie uma instacircncia
de Cliente Esta por sua vez possui o mesmo problema apresentado no modelo 2 duas dependecircncias Resumindo chegamos ao limite do que podemos fazer usando apenas o padratildeo Factory
Entra a Injeccedilatildeo de Dependecircncias
A injeccedilatildeo de dependecircncias (Dependency Injection ou DI em inglecircs) eacute uma forma de
inversatildeo de controle na qual o aspecto a ser invertido eacute como o proacuteprio nome jaacute diz a resoluccedilatildeo de dependecircncias Ao inveacutes do desenvolvedor definir manualmente quais as
instacircncias a serem criadas e injetadas como fizemos nos trecircs modelos anteriormente descritos delega-se esta tarefa a um container de inversatildeo de controle (IoC) veja o quadro Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle - evitando assim a necessidade de se implementar o padratildeo factory
Grosso modo podemos pensar no container de IoC como um factory ideal capaz de instanciar qualquer tipo de classe sem que fiquemos presos a uma famiacutelia especiacutefica de
objetos Poreacutem como veremos no caso do Spring este factory vai aleacutem agrave medida que tambeacutem controla o ciclo de vida dos objetos por ele gerenciados Para introduzirmos o conceito imagine que este container eacute uma classe maacutegica que sempre nos retorna um
objeto cujo tipo eacute exatamente aquele que estamos precisando O truque por traacutes desta
maacutegica seraacute exposto no decorrer deste artigo O que eacute uma dependecircncia
Eacute muito raro encontrarmos um software real e uacutetil composto por uma uacutenica classe Na esmagadora maioria das
vezes topamos com classes que possuem atributos cujo tipo satildeo outras classes Estes atributos que referenciam outros
tipos de classe satildeo o que costumamos chamar de dependecircncia
Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle
Se o nuacutecleo do Spring eacute chamado de Container de Inversatildeo de Controle (IoC de Inversion of Control em inglecircs)
porque estamos usando o termo injeccedilatildeo de dependecircncias Porque como bem observou Martin Fowler em seu artigo Inversion of Control Containers and the Dependency Injection Pattern 4 os containeres de inversatildeo de controle
como Spring Pico e outros aplicam um tipo muito especiacutefico de inversatildeo de controle
E neste momento uma segunda pergunta surge o que eacute inversatildeo de controle
Chama-se de inversatildeo de controle a teacutecnica de desenvolvimento na qual um
aspecto comportamental do sistema eacute delegado a uma entidade externa Um exemplo de inversatildeo de controle eacute o EJB O desenvolvedor implementa o
seu EJB e em seguida faz o deploy no servidor de aplicaccedilotildees sem precisar se preocupar com o modo como seu componente seraacute iniciado finalizado e
gerenciado porque neste caso eacute tudo feito pelo servidor Ao inveacutes de nos
preocuparmos com estas tarefas as delegamos a uma entidade externa que normalmente recebe o nome de container
A inversatildeo de controle esta no nuacutecleo do conceito de framework Ao
adotarmos um framework estamos reutilizando a estrutura de uma aplicaccedilatildeo
semi-pronta que finalizamos ao inserir nossos proacuteprios componentes
4 O artigo pode ser online neste endereccedilo httpwwwmartinfowlercomarticlesinjectionhtml
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
customizados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
dependecircncias acabariacuteamos com uma arquitetura similar agrave exposta na
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
FactoryDAOLivro
No novo modelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc
nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
fonte A partir destes dados ecomputacional o container eacute capaz de instanciar
instruamos a fazecirc-lo Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
consequumlecircncia temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees
Caso surja a necessidade de uma nova implementaccedilatildeo
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute
la como um arquivo jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s)necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara
Imagem 4 - Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
pendecircncias com Spring Framework 3
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute delegado
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido portanto que o termo Inversatildeo de Controle
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
com uma arquitetura similar agrave exposta na imagem 4
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das cnosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc-lo a partir de configuraccedilotildees que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
e usando o mecanismo de reflexatildeo provido pelocomputacional o container eacute capaz de instanciar e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees ja a necessidade de uma nova implementaccedilatildeo de alguma das abstraccedilotildees
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute-la jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s) de configuraccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara de ser executada
Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
delegado ao framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Inversatildeo de Controle eacute
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
imagem 4 Observe classes do
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
o ambiente e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolvedor se encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
de alguma das abstraccedilotildees
la distribuiacute-jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
ccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem-se desta maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
inversatildeo de dependecircncias cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle
Um moacutedulo de niacutevel mais
pertencente a um niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
contraacuterio Em nosso exemplo a classe
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
IDAOLivro O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo
Observe que as trecircs caracteriacute
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface
classe Cliente Como consequumlecircncia
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda acoplamento da classe Cliente
classe DAOLivro no segundo de apresentar uma terceira versatildeo do sistema cuja ar
A mudanccedila foi sutil apenas explicitamos a presenccedila de um
classe Cliente do tipo IDAOLivro
Cliente3 Agora podemos dizer que atingimos o menor esta classe
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
classe FactoryDAOLivro que possui como dependecircncia tod
presentes no sistema da interface evolua chegaremos a um momento no qual a classe
2 Este beliacutessimo artigo encontra
httpwwwobjectmentorcompublicationsdippd3 Poderiacuteamos tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Imagem 3 - Terceira versatildeo do nosso modelo
pendecircncias com Spring Framework 3
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo Dependency Invertion Principle2 Este princiacutepio nos diz duas coisas
Um moacutedulo de niacutevel mais alto jamais deve depender diretamente de outro m niacutevel inferior mas sim de uma abstraccedilatildeo
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
Em nosso exemplo a classe Cliente eacute um moacutedulo de niacutevel superior natildeo
interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta i
mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trataobrigatoriedade de se implementar a funccedilatildeo buscaPorAutor
Observe que as trecircs caracteriacutesticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
em uma implementaccedilatildeo especiacutefica da interface IDAOLivro natildeo afetaraacute diretamente a
consequumlecircncia o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar com maior facilidade elementos do nosso sistema para outros projetos
Mas este modelo ainda estaacute longe do ideal porque aumentamos o Cliente Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
no segundo incluiacutemos outra que eacute a classe FactoryIDAOLivro
de apresentar uma terceira versatildeo do sistema cuja arquitetura eacute exposta na imagem 3
sutil apenas explicitamos a presenccedila de um atributo daoLivro
IDAOLivro cuja instacircncia eacute definida pelo construtor da classe
Agora podemos dizer que atingimos o menor grau de acoplamento possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
que possui como dependecircncia todas as implementaccedilotildees
presentes no sistema da interface IDAOLivro Eacute quase certo que conforme este sistema
evolua chegaremos a um momento no qual a classe FactoryDAOLivro se tornaraacute um
Este beliacutessimo artigo encontra-se acessiacutevel gratuitamente no endereccedilo
httpwwwobjectmentorcompublicationsdippdf tambeacutem ter criado um setter para este atributo poreacutem o efeito seria o mesmo
Terceira versatildeo do nosso modelo
O que vimos no segundo modelo eacute na realidade a aplicaccedilatildeo do princiacutepio de
cunhado por Robert C Martin em 1996 no seu artigo The
alto jamais deve depender diretamente de outro
Abstraccedilotildees natildeo devem depender de detalhes de implementaccedilatildeo mas sim o
eacute um moacutedulo de niacutevel superior natildeo lhe interessa como os tiacutetulos dos livros satildeo obtidos mas sim que os mesmos sejam retornados
de alguma forma para que possa concluir o seu trabalho No primeiro modelo esta dependia diretamente de uma implementaccedilatildeo especiacutefica (o arquivo no formato textual) Jaacute
na segunda passa a depender apenas de uma abstraccedilatildeo que no caso eacute a nossa interface
O segundo postulado tambeacutem foi respeitado no segundo modelo Observe que as
distintas implementaccedilotildees de IDAOLivro natildeo influenciam de forma alguma esta interface mas sim o contraacuterio No caso todas as implementaccedilotildees especiacuteficas de IDAOLivro
seguem rigidamente as regras definidas pela interface que no caso trata-se da
sticas presentes em um design ruim natildeo se aplicam no
segundo modelo Nosso software natildeo eacute mais fraacutegil pois caso seja feita qualquer alteraccedilatildeo
natildeo afetaraacute diretamente a
o sistema agora eacute mais faacutecil de ser mantido (natildeo haacute
rigidez) e ainda mais interessante obtivemos mobilidade pois podemos agora transportar
porque aumentamos o grau de Enquanto na primeira versatildeo sua uacutenica dependecircncia era a
FactoryIDAOLivro Eacute hora
imagem 3
daoLivro na cuja instacircncia eacute definida pelo construtor da classe
possiacutevel para
Poreacutem por mais que nos esforcemos se continuarmos seguindo esta linha de
raciociacutenio sempre nos depararemos com problemas de acoplamento Basta observar a
as as implementaccedilotildees
Eacute quase certo que conforme este sistema
se tornaraacute um
se acessiacutevel gratuitamente no endereccedilo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
monstro de difiacutecil manutenccedilatildeo A cada nova implementaccedilatildeo de IDAOLivro precisaremos alteraacute-la e compilaacute-la novamente
Aleacutem deste problema temos outro eacute necessaacuteria uma classe que crie uma instacircncia
de Cliente Esta por sua vez possui o mesmo problema apresentado no modelo 2 duas dependecircncias Resumindo chegamos ao limite do que podemos fazer usando apenas o padratildeo Factory
Entra a Injeccedilatildeo de Dependecircncias
A injeccedilatildeo de dependecircncias (Dependency Injection ou DI em inglecircs) eacute uma forma de
inversatildeo de controle na qual o aspecto a ser invertido eacute como o proacuteprio nome jaacute diz a resoluccedilatildeo de dependecircncias Ao inveacutes do desenvolvedor definir manualmente quais as
instacircncias a serem criadas e injetadas como fizemos nos trecircs modelos anteriormente descritos delega-se esta tarefa a um container de inversatildeo de controle (IoC) veja o quadro Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle - evitando assim a necessidade de se implementar o padratildeo factory
Grosso modo podemos pensar no container de IoC como um factory ideal capaz de instanciar qualquer tipo de classe sem que fiquemos presos a uma famiacutelia especiacutefica de
objetos Poreacutem como veremos no caso do Spring este factory vai aleacutem agrave medida que tambeacutem controla o ciclo de vida dos objetos por ele gerenciados Para introduzirmos o conceito imagine que este container eacute uma classe maacutegica que sempre nos retorna um
objeto cujo tipo eacute exatamente aquele que estamos precisando O truque por traacutes desta
maacutegica seraacute exposto no decorrer deste artigo O que eacute uma dependecircncia
Eacute muito raro encontrarmos um software real e uacutetil composto por uma uacutenica classe Na esmagadora maioria das
vezes topamos com classes que possuem atributos cujo tipo satildeo outras classes Estes atributos que referenciam outros
tipos de classe satildeo o que costumamos chamar de dependecircncia
Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle
Se o nuacutecleo do Spring eacute chamado de Container de Inversatildeo de Controle (IoC de Inversion of Control em inglecircs)
porque estamos usando o termo injeccedilatildeo de dependecircncias Porque como bem observou Martin Fowler em seu artigo Inversion of Control Containers and the Dependency Injection Pattern 4 os containeres de inversatildeo de controle
como Spring Pico e outros aplicam um tipo muito especiacutefico de inversatildeo de controle
E neste momento uma segunda pergunta surge o que eacute inversatildeo de controle
Chama-se de inversatildeo de controle a teacutecnica de desenvolvimento na qual um
aspecto comportamental do sistema eacute delegado a uma entidade externa Um exemplo de inversatildeo de controle eacute o EJB O desenvolvedor implementa o
seu EJB e em seguida faz o deploy no servidor de aplicaccedilotildees sem precisar se preocupar com o modo como seu componente seraacute iniciado finalizado e
gerenciado porque neste caso eacute tudo feito pelo servidor Ao inveacutes de nos
preocuparmos com estas tarefas as delegamos a uma entidade externa que normalmente recebe o nome de container
A inversatildeo de controle esta no nuacutecleo do conceito de framework Ao
adotarmos um framework estamos reutilizando a estrutura de uma aplicaccedilatildeo
semi-pronta que finalizamos ao inserir nossos proacuteprios componentes
4 O artigo pode ser online neste endereccedilo httpwwwmartinfowlercomarticlesinjectionhtml
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
customizados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
dependecircncias acabariacuteamos com uma arquitetura similar agrave exposta na
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
FactoryDAOLivro
No novo modelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc
nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
fonte A partir destes dados ecomputacional o container eacute capaz de instanciar
instruamos a fazecirc-lo Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
consequumlecircncia temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees
Caso surja a necessidade de uma nova implementaccedilatildeo
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute
la como um arquivo jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s)necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara
Imagem 4 - Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
pendecircncias com Spring Framework 3
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute delegado
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido portanto que o termo Inversatildeo de Controle
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
com uma arquitetura similar agrave exposta na imagem 4
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das cnosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc-lo a partir de configuraccedilotildees que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
e usando o mecanismo de reflexatildeo provido pelocomputacional o container eacute capaz de instanciar e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees ja a necessidade de uma nova implementaccedilatildeo de alguma das abstraccedilotildees
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute-la jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s) de configuraccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara de ser executada
Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
delegado ao framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Inversatildeo de Controle eacute
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
imagem 4 Observe classes do
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
o ambiente e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolvedor se encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
de alguma das abstraccedilotildees
la distribuiacute-jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
ccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem-se desta maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
monstro de difiacutecil manutenccedilatildeo A cada nova implementaccedilatildeo de IDAOLivro precisaremos alteraacute-la e compilaacute-la novamente
Aleacutem deste problema temos outro eacute necessaacuteria uma classe que crie uma instacircncia
de Cliente Esta por sua vez possui o mesmo problema apresentado no modelo 2 duas dependecircncias Resumindo chegamos ao limite do que podemos fazer usando apenas o padratildeo Factory
Entra a Injeccedilatildeo de Dependecircncias
A injeccedilatildeo de dependecircncias (Dependency Injection ou DI em inglecircs) eacute uma forma de
inversatildeo de controle na qual o aspecto a ser invertido eacute como o proacuteprio nome jaacute diz a resoluccedilatildeo de dependecircncias Ao inveacutes do desenvolvedor definir manualmente quais as
instacircncias a serem criadas e injetadas como fizemos nos trecircs modelos anteriormente descritos delega-se esta tarefa a um container de inversatildeo de controle (IoC) veja o quadro Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle - evitando assim a necessidade de se implementar o padratildeo factory
Grosso modo podemos pensar no container de IoC como um factory ideal capaz de instanciar qualquer tipo de classe sem que fiquemos presos a uma famiacutelia especiacutefica de
objetos Poreacutem como veremos no caso do Spring este factory vai aleacutem agrave medida que tambeacutem controla o ciclo de vida dos objetos por ele gerenciados Para introduzirmos o conceito imagine que este container eacute uma classe maacutegica que sempre nos retorna um
objeto cujo tipo eacute exatamente aquele que estamos precisando O truque por traacutes desta
maacutegica seraacute exposto no decorrer deste artigo O que eacute uma dependecircncia
Eacute muito raro encontrarmos um software real e uacutetil composto por uma uacutenica classe Na esmagadora maioria das
vezes topamos com classes que possuem atributos cujo tipo satildeo outras classes Estes atributos que referenciam outros
tipos de classe satildeo o que costumamos chamar de dependecircncia
Injeccedilatildeo de Dependecircncias ou Inversatildeo de Controle
Se o nuacutecleo do Spring eacute chamado de Container de Inversatildeo de Controle (IoC de Inversion of Control em inglecircs)
porque estamos usando o termo injeccedilatildeo de dependecircncias Porque como bem observou Martin Fowler em seu artigo Inversion of Control Containers and the Dependency Injection Pattern 4 os containeres de inversatildeo de controle
como Spring Pico e outros aplicam um tipo muito especiacutefico de inversatildeo de controle
E neste momento uma segunda pergunta surge o que eacute inversatildeo de controle
Chama-se de inversatildeo de controle a teacutecnica de desenvolvimento na qual um
aspecto comportamental do sistema eacute delegado a uma entidade externa Um exemplo de inversatildeo de controle eacute o EJB O desenvolvedor implementa o
seu EJB e em seguida faz o deploy no servidor de aplicaccedilotildees sem precisar se preocupar com o modo como seu componente seraacute iniciado finalizado e
gerenciado porque neste caso eacute tudo feito pelo servidor Ao inveacutes de nos
preocuparmos com estas tarefas as delegamos a uma entidade externa que normalmente recebe o nome de container
A inversatildeo de controle esta no nuacutecleo do conceito de framework Ao
adotarmos um framework estamos reutilizando a estrutura de uma aplicaccedilatildeo
semi-pronta que finalizamos ao inserir nossos proacuteprios componentes
4 O artigo pode ser online neste endereccedilo httpwwwmartinfowlercomarticlesinjectionhtml
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
customizados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
dependecircncias acabariacuteamos com uma arquitetura similar agrave exposta na
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
FactoryDAOLivro
No novo modelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc
nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
fonte A partir destes dados ecomputacional o container eacute capaz de instanciar
instruamos a fazecirc-lo Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
consequumlecircncia temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees
Caso surja a necessidade de uma nova implementaccedilatildeo
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute
la como um arquivo jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s)necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara
Imagem 4 - Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
pendecircncias com Spring Framework 3
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute delegado
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido portanto que o termo Inversatildeo de Controle
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
com uma arquitetura similar agrave exposta na imagem 4
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das cnosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc-lo a partir de configuraccedilotildees que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
e usando o mecanismo de reflexatildeo provido pelocomputacional o container eacute capaz de instanciar e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees ja a necessidade de uma nova implementaccedilatildeo de alguma das abstraccedilotildees
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute-la jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s) de configuraccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara de ser executada
Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
delegado ao framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Inversatildeo de Controle eacute
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
imagem 4 Observe classes do
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
o ambiente e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolvedor se encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
de alguma das abstraccedilotildees
la distribuiacute-jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
ccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem-se desta maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
customizados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
dependecircncias acabariacuteamos com uma arquitetura similar agrave exposta na
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
FactoryDAOLivro
No novo modelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc
nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
fonte A partir destes dados ecomputacional o container eacute capaz de instanciar
instruamos a fazecirc-lo Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
consequumlecircncia temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees
Caso surja a necessidade de uma nova implementaccedilatildeo
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute
la como um arquivo jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s)necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara
Imagem 4 - Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
pendecircncias com Spring Framework 3
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
nos lembramos do processo de preenchimento de formulaacuterios que eacute delegado
framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Apoacutes estes exemplos fica niacutetido portanto que o termo Inversatildeo de Controle
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
das dependecircncias das classes de nosso projeto
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
com uma arquitetura similar agrave exposta na imagem 4
que o Container natildeo possui nenhuma dependecircncia direta com nenhuma das cnosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
eacute feito pelo container que eacute instruiacutedo a fazecirc-lo a partir de configuraccedilotildees que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
e usando o mecanismo de reflexatildeo provido pelocomputacional o container eacute capaz de instanciar e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolved
encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
distribuir nas mais variadas situaccedilotildees ja a necessidade de uma nova implementaccedilatildeo de alguma das abstraccedilotildees
presentes no sistema tudo o que o desenvolvedor precisa fazer eacute implementaacute-la jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
sistema e em seguida alterar o(s) arquivo(s) de configuraccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem
maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
processo de recompilaccedilatildeo se torna uma tarefa muito mais rara de ser executada
Nosso modelo apoacutes aplicar Injeccedilatildeo de Dependecircncias
ados No caso de aplicaccedilotildees web este comportamento fica niacutetido quando
delegado ao framework ao inveacutes de ser implementado manualmente pelo desenvolvedor
Inversatildeo de Controle eacute
geneacuterico demais para ser adotado no caso do Spring aonde o foco eacute a resoluccedilatildeo
Voltando ao nosso exemplo inicial ao aplicarmos o padratildeo de injeccedilatildeo de
imagem 4 Observe classes do
nosso sistema Outro fator interessante a ser observado eacute a ausecircncia da classe
odelo todo o processo de instanciaccedilatildeo e preenchimento de dependecircncias
que podem estar nos mais variados formatos desde arquivos no formato XML ateacute anotaccedilotildees em coacutedigo
o ambiente e injetar todas as dependecircncias que noacutes o
Uma das grandes vantagens deste modelo eacute que neste estaacutegio o desenvolvedor se encontra proacuteximo do desacoplamento quase total entre seus componentes Como
temos sistemas com qualidade muito superior mais faacuteceis de manter e
de alguma das abstraccedilotildees
la distribuiacute-jar (ou class mesmo) incluir a implementaccedilatildeo no classpath do
ccedilatildeo do container sem a
necessidade de recompilar o sistema para se adequar a esta nova situaccedilatildeo Obteacutem-se desta maneira mobilidade total do sistema visto que com o nuacutecleo pronto e estabilizado o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Spring Framework entra em cena O objetivo do Spring Framework eacute simplificar o desenvolvimento de aplicaccedilotildees
corporativas Na imagem 5 podemos ver todos os moacutedulos que compotildeem o framework que eacute uma alternativa viaacutevel agrave plataforma Java Enterprise Edition Este incriacutevel
framework possibilitou usando apenas POJOs obter os mesmos resultados que ateacute entatildeo
soacute eram possiacuteveis com EJB E tudo isto graccedilas agrave aplicaccedilatildeo do conceito de injeccedilatildeo de
dependecircncias Spring pode fazer inuacutemeras coisas mas quando nos focamos apenas no seu nuacutecleo
percebemos que estamos lidando na realidade com um container de injeccedilatildeo de
dependecircncias e programaccedilatildeo orientada a aspectos leve Para melhor entender a sua
definiccedilatildeo conveacutem estudar suas partes Por que leve Spring eacute natildeo intrusivo Se sua aplicaccedilatildeo eacute baseada no Spring eacute
possiacutevel que suas classes natildeo venham a ter qualquer dependecircncia direta com o
framework Nada mais natural visto que o problema do alto acoplamento eacute justamente o
que o conceito de injeccedilatildeo de dependecircncias visa resolver Programaccedilatildeo orientada a aspectos O Spring oferece desde sua primeira versatildeo
suporte a programaccedilatildeo orientada a aspectos Esta eacute uma teacutecnica poderosa que permite ao
desenvolvedor separar a loacutegica de negoacutecios de serviccedilos de infra-estrutura presente em nossa aplicaccedilatildeo Eacute importante mencionar esta caracteriacutestica visto que se trata do outro pilar do framework aleacutem do container de injeccedilatildeo de dependecircncias
Poreacutem nosso foco eacute o container de injeccedilatildeo de dependecircncias Sendo assim iremos
tratar aqui apenas do moacutedulo Core Container do Spring Como seraacute visto eacute uma
ferramenta que consegue ser ao mesmo tempo extremamente poderosa e simples de se usar E esta eacute a beleza deste container
Imagem 5 Componentes do Spring Framework Nosso foco eacute no Core Container
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3
httpdevkicoitextocombr
O container de injeccedilatildeo de dependecircnciasChegou o momento de col
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
Para este artigo seraacute usada a versatildeo
modular Isto quer dizer quacompanham a distribuiccedilatildeo
As dependecircncias do Container
Iremos usar apenas os arquivos que compotildeem o
distribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo org
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
orgspringframework beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans Precisaremos portanto
expression A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficiallogging-[nuacutemero da versatildeo]jar em seu classpath
Como o container funciona
Para que o container seja uacutetil primeiro
suas configuraccedilotildees podem vir eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou
Uma vez alimentado com estas cointernamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas configuraccedilotildees como uma receita
instanciar um bean Estas receitas de beans no entanto
instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
especificam qual deve ser o tempo de vidaser removido do container De imediato o Spring nos fornece 5 tipos de escopo prototype request session e global session
visto que os demais satildeo usados no dese
foco do nosso artigo Na tabela 1
5 httpwwwspringframeworkorg 6 httpcommonsapacheorglogging7 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprio
Imagem 6 Funcionamento de um container
pendecircncias com Spring Framework 3
container de injeccedilatildeo de dependecircncias Chegou o momento de colocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial
seraacute usada a versatildeo 302 O Spring eacute um framework extremamente
modular Isto quer dizer que natildeo precisamos usar todos os arquivos JAR que
As dependecircncias do Container
usar apenas os arquivos que compotildeem o Core Container do Springdistribuiccedilatildeo oficial estes satildeo nomeados seguindo o seguinte padratildeo orgspringframework [nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
dos moacutedulos beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
que pode ser obtida em seu site oficial6 Deveraacute ser adicionado o arquivo commons
[nuacutemero da versatildeo]jar em seu classpath
er seja uacutetil primeiro precisamos configuraacute-lo No caso do Spring de basicamente trecircs fontes arquivos no formato XML (que
eacute a opccedilatildeo mais comum) anotaccedilotildees em coacutedigo fonte ou programaticamente7 alimentado com estas configuraccedilotildees o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
definem quais classes devem ser instanciadas suas interdependecircncias Pense nas receita a ser seguida pelo Spring quando for necessaacuterio
Estas receitas de beans no entanto dizem mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
qual deve ser o tempo de vida ou seja quando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo global session Destes apenas trataremos dos dois primeiros
visto que os demais satildeo usados no desenvolvimento de aplicaccedilotildees web o que foge do
tabela 1 eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
httpcommonsapacheorglogging - Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11
O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
desenvolvedor pode criar os seus proacuteprios parsers de configuraccedilatildeo caso seja de seu interesse
Funcionamento de um container
ocar toda esta teoria em praacutetica Para usar o container de
injeccedilatildeo do Spring eacute necessaacuterio baixar a uacuteltima versatildeo do framework em seu site oficial5 302 O Spring eacute um framework extremamente
e natildeo precisamos usar todos os arquivos JAR que
do Spring Na springframework
[nome do moacutedulo][nuacutemero da versatildeo]RELEASEjar Sendo assim o arquivo
beans302RELEASEjar por exemplo eacute na realidade o moacutedulo
beans context contextsupport core e
A uacutenica dependecircncia externa do container eacute a biblioteca Commons Logging
Deveraacute ser adicionado o arquivo commons-
No caso do Spring trecircs fontes arquivos no formato XML (que
o container iraacute armazenar
internamente representaccedilotildees dos objetos a serem gerenciados Estas representaccedilotildees
Pense nas g quando for necessaacuterio
mais do que apenas quais classes instanciar e suas interdependecircncias definem tambeacutem o escopo de cada bean Escopos
uando um bean jaacute instanciado deveraacute
De imediato o Spring nos fornece 5 tipos de escopo singleton Destes apenas trataremos dos dois primeiros
nvolvimento de aplicaccedilotildees web o que foge do
eacute possiacutevel conhecer a descriccedilatildeo destes 5 escopos
Na escrita deste artigo a uacuteltima versatildeo disponiacutevel eacute a 11 O nuacutecleo do Spring eacute totalmente desacoplado de uma fonte especiacutefica de configuraccedilotildees Sendo assim o
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Tabela 1 Escopos do Spring
Escopo Descriccedilatildeo
singleton Trata-se do escopo default do Spring O container manteacutem uma
uacutenica instacircncia do bean definido prototype O Spring sempre retorna uma nova instacircncia do bean caso o
mesmo seja requerido request Usado em aplicaccedilotildees web define que a instacircncia do bean possuiraacute
o mesmo tempo de vida que uma requisiccedilatildeo HTTP session Adotado em aplicaccedilotildees web define que a instacircncia do bean se
encontraraacute armazenada na sessatildeo do usuaacuterio sendo imediatamente
destruiacutedo junto com esta global session Tambeacutem usado em aplicaccedilotildees web armazena a instacircncia do bean
em uma sessatildeo global
Configurado e pronto para o uso entra a classe cliente que simplesmente faraacute
requisiccedilotildees ao container do Spring por um bean especiacutefico
Instanciando o Container
O Spring oferece dois tipos de container BeanFactory e ApplicationContext Nossa primeira boa praacutetica portanto diz respeito a qual tipo deveraacute ser selecionado
BeanFactory eacute na realidade uma interface presente no pacote
orgspringframeworkbeansfactory que representa o container mais simples fornecido pelo framework oferecendo apenas suporte a injeccedilatildeo de dependecircncias e gerenciamento
de ciclo de vida dos beans O framework jaacute vem com algumas implementaccedilotildees desta interface sendo a mais
usada orgspringframeworkbeansfactoryxmlXmlBeanFactory que lecirc as configuraccedilotildees
do container a partir de um documento XML Normalmente opta-se por usar o BeanFactory quando o ambiente computacional
oferece restriccedilotildees mais incisivas como por exemplo um Applet Jaacute ApplicationContext que tambeacutem eacute uma interface presente no pacote
orgspringframeworkcontext eacute uma extensatildeo de BeanFactory e oferece todos os serviccedilos
deste e mais alguns como internacionalizaccedilatildeo extensibilidade e gerenciamento de
eventos As implementaccedilotildees mais usadas desta interface satildeo
ClassPathXmlApplicationContext e FileSystemXmlApplicationContext Ambas consomem suas configuraccedilotildees a partir de documentos no formato XML e encontram-se no pacote orgspringframeworkcontextsupport A diferenccedila entre uma e outra eacute apenas
aonde os documentos XML se encontram Enquanto a primeira o busca no classpath da aplicaccedilatildeo a outra o encontra no sistema de arquivos no qual a aplicaccedilatildeo eacute executada
Na esmagadora maioria das vezes vocecirc acabaraacute usando ApplicationContext a
natildeo ser que possua excelentes razotildees para natildeo fazecirc-lo Sendo assim no transcorrer deste artigo usaremos apenas ApplicationContext
Haacute uma diferenccedila de comportamento entre BeanFactory e ApplicationContext No caso do ApplicationContext todos os beans com escopo singleton satildeo automaticamente
carregados por default ao contraacuterio de BeanFactory em que beans pertencentes a este escopo soacute satildeo inicializados na primeira vez em que satildeo requeridos Esta eacute uma das razotildees
pelas quais se costuma usar BeanFactory
Oculte seu Container Uma das principais vantagens do Spring eacute ser leve sendo assim devemos proteger
esta caracteriacutestica ao maacuteximo possiacutevel De preferecircncia apenas uma classe deveraacute
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
referenciar o container do Spring ocultando-o do restante do sistema Na listagem 1 podemos ver como obter este resultado Eacute uma classe muito simples mas que nos diz muita coisa
Listagem 1 Ocultando o Container de Injeccedilatildeo de Dependecircncias
public class Container private ApplicationContext contextoSpring private ApplicationContext getContextoSpring() if (contextoSpring == null) contextoSpring = new ClassPathXmlApplicationContext(dispringxml) return contextoSpring public Object getBean(String nome) ApplicationContext contexto = getContextoSpring() if (contexto = null) try return contextogetBean(nome) catch (NoSuchBeanDefinitionException ex) return null return null public static synchronized Container getInstancia() return _instancia private static Container _instancia = new Container() private Container()
O processo de instanciaccedilatildeo do container eacute caro do ponto de vista computacional
Sendo assim eacute interessante mantermos uma uacutenica instacircncia de nosso ApplicationContext o que conseguimos a partir da implementaccedilatildeo do padratildeo singleton na classe Container Assim garantimos que uma uacutenica instacircncia do container seraacute usada durante todo o
processo de execuccedilatildeo do nosso sistema O que eacute Padratildeo de Projeto Singleton
O padratildeo de projeto Singleton tem como objetivo garantir que uma uacutenica instacircncia de uma classe seja
criada aleacutem de tambeacutem fornecer um uacutenico ponto de acesso a mesma Seu uso eacute um tanto quanto
controverso sendo normalmente usado apenas em situaccedilotildees como a exposta na listagem 1 deste artigo
Na listagem 1 tambeacutem vemos basicamente tudo o que vocecirc precisa saber a respeito
de como obter um bean gerenciado pelo container Basta executar a funccedilatildeo getBean que recebe como paracircmetro o nome do bean presente no container Seu valor de retorno eacute do
tipo Object Se no container natildeo houver um bean com este nome seraacute disparada uma
exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException razatildeo pela qual lidamos com esta exceccedilatildeo dentro da funccedilatildeo getBean
Observe que a classe Container possui apenas um uacutenico meacutetodo puacuteblico no caso
getBean Isto nos ajuda a garantir que nenhuma outra classe do projeto venha a ter uma dependecircncia direta com o Spring garantindo assim a leveza do framework
Alimentando o Container com XML
Para que o container possa nos retornar um bean antes ele precisa saber o que e como instanciar E eacute neste momento que a configuraccedilatildeo entra em cena Tal como dito
anteriormente haacute basicamente trecircs maneiras de se configurar o Spring atraveacutes de
documentos no formato XML usando anotaccedilotildees ou programaticamente
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Cada uma destas abordagens apresenta suas vantagens e desvantagens que veremos no transcorrer deste artigo poreacutem dada sua natureza eacute interessante comeccedilar pela
configuraccedilatildeo via XML pois esta expotildee todos os recursos do Spring que seratildeo expostos
no restante deste artigo Na listagem 2 podemos ver como nossa aplicaccedilatildeo inicial pode
ser configurada usando este formato
Listagem 2 Configuraccedilatildeo do Spring de nossa aplicaccedilatildeo Inicial
ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsdgt ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt ltbean id=daoLivro class=diDAOLivroTexto scope=prototypegt ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbeansgt
O elemento raiz do documento eacute beans Cada bean gerenciado pelo container eacute
definido pela tag bean Na listagem 2 podemos ver nossa aplicaccedilatildeo configurada para
trabalhar com um uma implementaccedilatildeo de IDAOLivro que usa como fonte de dados um
arquivo textual O atributo bean possui apenas um atributo obrigatoacuterio que eacute o class que especifica
qual classe deveraacute ser instanciada O atributo id eacute usado para nomear os beans
gerenciados pelo container Sendo assim na listagem 2 definimos dois beans cliente e daoLivro
No bean cliente podemos ver a aplicaccedilatildeo da injeccedilatildeo de dependecircncias No interior
da tag bean que o representa haacute a tag property Esta tag possui o atributo obrigatoacuterio
name que identifica qual o nome da propriedade que deveraacute ser atribuiacuteda pelo container Spring utiliza o padratildeo JavaBeans Sendo assim a classe Cliente deveraacute possuir um setter
para a propriedade daoLivro o que de fato possui tal como pode ser conferido na listagem 3 Na tag property observa-se um outro atributo ref O valor deste atributo eacute o
nome do bean que deveraacute ser injetado que no caso eacute o bean daoLivro Eacute interessante observar que a tag property tambeacutem eacute usada para definir o valor de
propriedades do tipo string ou primitivas de um bean Observe que na listagem 2 definimos a propriedade arquivo do bean daoLivro com o valor livrostxt usando o
atributo value Caso o atributo seja do tipo numeacuterico o Spring se encarregaraacute de fazer a
conversatildeo necessaacuteria para o usuaacuterio
Listagem 3 A classe Cliente
public class Cliente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao public void buscar(String valor) ListltStringgt titulos = getDaoLivro()getLivrosAutor(valor) for (String titulo titulos) Systemoutprintln(titulo) public Cliente() public Cliente(IDAOLivro dao) setDaoLivro(dao)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Os tipos de injeccedilatildeo de dependecircncia
No Spring a injeccedilatildeo de dependecircncias pode ser feita de duas formas por setter ou
construtor Acima acabamos de ver a injeccedilatildeo por setter Este tipo de injeccedilatildeo eacute executado
em duas etapas Na primeira o construtor default da classe definida par ao bean eacute
executado gerando uma nova instacircncia para em seguida serem executados os setters
definidos pelas tags property presentes no interior da tag bean Sendo assim quando for adotar a injeccedilatildeo de dependecircncias por setter eacute obrigatoacuteria a presenccedila do construtor
default Jaacute a injeccedilatildeo de dependecircncias por construtor eacute feita definindo-se qual construtor
deveraacute ser executado ao criarmos uma nova instacircncia do bean A listagem 4 expotildee como
o mesmo efeito que obtivemos usando a injeccedilatildeo por setter pode ser obtido ao adotarmos a
injeccedilatildeo por construtor
Listagem 4 Injeccedilatildeo de dependecircncias por construtor
ltDefinindo o construtor por tipo ltbean id=clientePorTipo class=diClientegt
ltconstructor-arg type=diIDAOLivro ref=daoLivrogt ltbeangt
ltDefinindo pela ordem do atributo do construtor ltbean id=clientePorOrdem class=diClientegt ltconstructor-arg index=0 ref=daoLivrogt ltbeangt
Para fazer a injeccedilatildeo por construtor usamos a tag constructor-arg Haacute duas opccedilotildees
para se definir quais os valores de cada atributo do construtor A mais recomendada eacute por
tipo Neste caso constructor-arg deveraacute receber um atributo chamado type (tal como na listagem 4) que identifique qual o tipo do argumento O segundo atributo poderaacute ser tanto
ref caso estejamos referenciando outro bean quanto value se estivermos nos referindo a um atributo primitivo ou string
A segunda opccedilatildeo eacute definir os valores dos atributos do construtor a partir de sua ordem Na listagem 4 podemos ver como isto eacute feito no bean clientePorOrdem No caso ao inveacutes de usarmos o atributo type usamos index que define qual atributo a partir da sua ordem (sempre iniciando a partir do zero) Esta opccedilatildeo eacute uacutetil para se evitar ambiguumlidade na escolha do construtor caso haja mais de um paracircmetro pertencente a um mesmo tipo
Injeccedilatildeo por setter ou construtor
Como regra geral opta-se pela injeccedilatildeo por construtores para as dependecircncias
obrigatoacuterias e injeccedilatildeo por setter para as dependecircncias opcionais Os puristas preferem a
injeccedilatildeo por construtores porque assim temos a garantia de que ao obtermos um bean
estamos lidando com uma instacircncia completa com todas as dependecircncias obrigatoacuterias
preenchidas No entanto a equipe de desenvolvimento do Spring incentiva a injeccedilatildeo por setter
pois assim evita-se a criaccedilatildeo de construtores com vaacuterios atributos alguns dos quais definindo inclusive dependecircncias opcionais Eacute uma maneira de influenciar os
desenvolvedores a evitarem a escrita destes construtores que acabam dificultando a manutenccedilatildeo
Outra vantagem da injeccedilatildeo por setter eacute que ela nos permite reconfigurar a instacircncia
apoacutes obtida visto que tudo o que o desenvolvedor precisa fazer eacute passar uma nova
dependecircncia ao setter em questatildeo Se a pergunta vou precisar alterar alguma
dependecircncia de minha instacircncia apoacutes obtida for positiva a injeccedilatildeo por setter deveraacute ser
adotada
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Dando nome aos beans
Natildeo precisamos nomear um bean Caso natildeo o faccedilamos o proacuteprio Spring iraacute criar
um nome interno para o bean mapeado e caso este bean sem nome seja o uacutenico de seu
tipo isto eacute o uacutenico bean pertencente a determinada classe podemos inclusive obtecirc-lo usando o meacutetodo sobrescrito getBean(Class classe) do ApplicationContext
Mas esta obviamente natildeo eacute a melhor alternativa Afinal de contas nosso sistema
pode crescer e outros beans pertencentes agrave mesma classe podem acabar no nosso arquivo
de configuraccedilatildeo E neste caso ao tentar obter um bean pela sua classe ao inveacutes de pelo
seu nome obteriacuteamos uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException nos informando que haacute mais de um bean mapeado para aquele tipo especiacutefico
Sendo assim eacute fundamental saber como dar nome aos nossos beans A classe bean possui dois atributos para que possamos executar esta tarefa O primeiro deles jaacute vimos
nas listagens 2 e 4 Trata-se do atributo id Usamos este atributo quando queremos definir um nome uacutenico para nossos beans
Ao definirmos este atributo para o bean garantimos que em nosso container soacute poderaacute
existir um bean como aquele nome Eacute uma boa praacutetica usaacute-lo por outra razatildeo alguns
parseadores de XML oferecem otimizaccedilotildees para este atributo o que pode nos
proporcionar ganhos em performance e validaccedilatildeo destes documentos visto que o atributo id eacute o mesmo definido na especificaccedilatildeo do formato XML pelo W3C
Nossa outra opccedilatildeo eacute o atributo name que nos permite dar um ou mais nomes para um bean Eacute tambeacutem usado quando eacute necessaacuterio nomear um bean usando caracteres
especiais o que natildeo eacute permitido na especificaccedilatildeo XML No caso de um bean possuir mais
de um nome estes podem ser separados por espaccedilo ponto e viacutergula () ou viacutergulas () Na
listagem 5 podemos ver alguns exemplos
Listagem 5 Um bean com mais de um nome
ltbean name=clienteexemplo class=diClientegtltbeangt ltbean name=cliente exemplo class=diClientegtltbeangt ltbean name=clienteexemplo class=diClientegtltbeangt
Eacute comum oferecer mais de um nome a um determinado bean em projetos maiores
nos quais possam ocorrer situaccedilotildees nas quais times diferentes trabalhem em subsistemas distintos a serem integrados Poreacutem na esmagadora maioria das vezes o ideal eacute que cada
bean possua um uacutenico nome a fim de se evitar excessos de nomenclatura que acabem por
gerar confusotildees dentro da equipe Eacute uma boa praacutetica adotar padrotildees de nomenclatura aos beans Um padratildeo bastante
adotado eacute o de se aplicar prefixos aos nomes dos beans que exponham sua finalidade
como por exemplo o prefixo dao a todos os beans que implementem o padratildeo de projeto
DAO
Modularizando a configuraccedilatildeo
Uma das principais criacuteticas agrave configuraccedilatildeo no formato XML eacute a extensatildeo que estes
documentos possam vir a tomar Realmente eacute um tanto trabalhoso dar manutenccedilatildeo em
arquivos gigantescos poreacutem eacute possiacutevel sanar este problema dividindo a configuraccedilatildeo em
arquivos distintos Nestes casos cada arquivo de configuraccedilatildeo pode representar uma
camada loacutegica do sistema ou um moacutedulo de sua arquitetura Haacute duas maneiras de se modularizar a configuraccedilatildeo A primeira delas eacute atraveacutes da
tag ltimportgt que pode ser inserida em seus documentos XML tal como exemplificado na listagem 6
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Listagem 6 Usando a tag ltimportgt
ltbeansgt ltimport resource=servicosxmlgt ltimport resource=daodaosxmlgt ltbean id=cliente class=diClientegt ltbeansgt
A tag import possui o atributo obrigatoacuterio resource que define qual arquivo deveraacute
ser importado para a configuraccedilatildeo do Spring Os caminhos dos arquivos a serem
importados sempre satildeo relativos ao do arquivo que estaacute fazendo a importaccedilatildeo Sendo
assim se o arquivo da listagem 6 estivesse dentro do classpath do sistema no diretoacuterio
direcursos o arquivo importado servicosxml tambeacutem estaria neste mesmo diretoacuterio e
daosxml se encontraria no path direcursosdao O outro modo de obter o mesmo resultado eacute usando um construtor especial
oferecido tanto por ClassPathXmlApplicationContext quanto FileSystemApplicationContext que recebe como paracircmetros um array de strings
fornecendo os caminhos para os arquivos de configuraccedilatildeo a serem usados A listagem 7 exemplifica este processo usando a classe ClassPathXmlApplicationContext
Listagem 7 Modularizando a configuraccedilatildeo com o construtor especial String[] arquivos = direcursosspringxml direcursosservisosxml direcursosdaodaosxml ApplicationContext contextoSpring = new ClassPathXmlApplicationContext(arquivos)
Dentre as duas opccedilotildees a princiacutepio eacute mais interessante a primeira visto que natildeo eacute
necessaacuterio recompilar o coacutedigo fonte caso seja necessaacuterio adicionar algum novo arquivo
de configuraccedilatildeo ao container No entanto a segunda opccedilatildeo se mostra interessante em
situaccedilotildees nas quais a escolha dos arquivos de configuraccedilatildeo envolvam alguma loacutegica
interna do seu sistema
Escopo Singleton vs Prototype
Por padratildeo todo bean gerenciado pelo Spring possui escopo singleton Eacute
fundamental compreender a diferenccedila entre os dois escopos baacutesicos oferecidos pelo
Spring para evitarmos problemas no futuro Tal como exposto na tabela 1 quando um bean se encontra no escopo singleton o
Spring se encarregaraacute de manter uma uacutenica instacircncia deste bean sobre seu controle Sendo
assim toda vez que estivermos chamando o bean cliente definido na listagem 2 estaremos obtendo a mesma instacircncia da classe diCliente No entanto eacute importante
observar que estamos lidando aqui com um singleton relativo visto que nada impede que criemos fora do container uma instacircncia diferente desta mesma classe chamando seu
construtor padratildeo por exemplo Um fator que precisa ser levado em conta eacute que o BeanFactory e o
ApplicationContext adotam poliacuteticas diferentes com relaccedilatildeo a beans com escopo
singleton Quando o ApplicationContext eacute inicializado por padratildeo todos os beans com
escopo singleton satildeo instanciados e possuem suas dependecircncias injetadas ao passo que no BeanFactory estes soacute seratildeo preparados no momento em que forem chamados pela primeira vez
Jaacute no caso do prototype sempre que pedirmos ao container um bean que pertenccedila a
este escopo obteremos uma nova instacircncia Isto nos traacutes um certo impacto na
performance visto que sempre ocorreraacute o processo de preparaccedilatildeo do bean que eacute
composto por duas etapas instanciaccedilatildeo do mesmo e injeccedilatildeo das dependecircncias Na praacutetica utiliza-se o padratildeo singleton para beans mais complexos e que natildeo
armazenem estado como por exemplo a classe SessionFactory do Hibernate Uma situaccedilatildeo para a qual eacute necessaacuterio ficar atento eacute quando um bean com escopo
singleton possui uma dependecircncia com escopo prototype Eacute preciso ter consciecircncia de
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
que a injeccedilatildeo de dependecircncias em um bean soacute eacute feita no momento em que o bean eacute
instanciado Sendo assim a dependecircncia com escopo prototype injetada no bean singleton
apenas uma vez Se vocecirc quiser no entanto que o seu bean com escopo singleton sempre obtenha
uma nova instacircncia de sua dependecircncia com escopo prototype uma soluccedilatildeo eacute tornar este
bean consciente da existecircncia do container de injeccedilatildeo de dependecircncias Esta natildeo eacute uma
boa praacutetica pois estamos adicionando peso ao Spring visto que agora uma classe de
negoacutecios da nossa aplicaccedilatildeo passa a possuir uma dependecircncia direta com o container de
injeccedilatildeo de dependecircncias Mas caso seja de fato necessaacuterio basta que sua classe implemente a interface
orgspringframeworkcontextApplicationContextAware tal como a versatildeo alternativa da classe Cliente que encontra-se exposta na listagem 8
Listagem 8 um bean com consciecircncia do container de injeccedilatildeo de dependecircncias public class Cliente implements ApplicationContextAware o restante da classe eacute igual private ApplicationContext applicationContext public ApplicationContext getContextoSpring() return applicationContext public void setApplicationContext(ApplicationContext ac) throws BeansException thisapplicationContext = ac
O container do Spring iraacute injetar nas classes que implementem a interface
ApplicationContextAware uma instacircncia de si mesmo chamando o meacutetodo
setApplicationContext que recebe como paracircmetro uma instacircncia e ApplicationContext Sendo assim internamente a classe pode pedir ao container que sempre lhe retorne uma nova instacircncia de uma de suas dependecircncias cujo escopo seja singleton
Inicializaccedilatildeo tardia de beans singleton
Tal como falamos na seccedilatildeo anterior o ApplicationContext por default prepara todos
os beans com escopo singleton no momento em que eacute carregado Tal comportamento nem
sempre eacute adequado visto que haacute situaccedilotildees nas quais alguns beans satildeo usados somente em
circunstacircncias muito especiacuteficas Sendo assim porque carregaacute-los se talvez nem sejam necessaacuterios durante a execuccedilatildeo do sistema
A soluccedilatildeo para o problema eacute simples Basta adicionarmos o atributo lazy-init agrave tag
bean com o valor true Agora o bean soacute seraacute processado no momento em que for
requerido pela primeira vez Eacute possiacutevel incluir o atributo lazy-init na tag bean tambeacutem
assim altera-se o comportamento default de carregamento para todos os beans presentes naquele arquivo de configuraccedilatildeo
No entanto nem sempre esta eacute uma boa praacutetica Enquanto o sistema estiver em
desenvolvimento eacute interessante que todos os beans sejam carregados visto que assim seraacute possiacutevel encontrar erros de configuraccedilatildeo nesta etapa inicial do processo facilitando
assim a correccedilatildeo de erros
Autowiring
O container de injeccedilatildeo de dependecircncias do Spring pode automaticamente descobrir
quais as dependecircncias de um bean a partir de um recurso bastante interessante chamado
autowiring Como vantagem o desenvolvedor pode reduzir significativamente o nuacutemero
de propriedades e construtores que precisa especificar em seus arquivos de configuraccedilatildeo
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
O funcionamento do autowiring inicia-se quando marcamos um bean para que seja auto injetado8 pelo container Quando este bean for ser iniciado o container iraacute varrer
todos os atributos presentes em sua classe e para cada um verificaraacute entre as definiccedilotildees
de beans armazenada em seu interior a existecircncia de um bean que possa ser injetado
naquele ponto Encontrados todos os candidatos apropriados estes satildeo injetados no bean
Caso haja alguma ambiguumlidade o container natildeo saberaacute qual bean deve ser injetado e neste caso uma exceccedilatildeo do tipo orgspringframeworkbeansfactoryNoSuchBeanDefinitionException informando qual atributo natildeo pode ser injetado
A melhor maneira de entender este conceito eacute vecirc-lo em praacutetica Na listagem 9
podemos ver como configurar o Spring para tirar proveito deste recurso Podemos ver trecircs
beans definidos daoLivro cliente e autowired O primeiro seraacute injetado nos demais
Enquanto na definiccedilatildeo do bean cliente precisamos definir todas as dependecircncias
manualmente o mesmo natildeo eacute verdade com o bean autowired Repare que natildeo foi
necessaacuterio incluir em sua definiccedilatildeo nenhum construtor ou propriedade apenas o atributo
autowire com o valor byType Listagem 9 Usando autowiring ltbeansgt ltbean id=daoLivro class=diDAOLivroTextogt
ltproperty name=arquivo value=livrostxtgt ltbeangt
ltbean id=cliente class=diClientegt ltproperty name=daoLivro ref=daoLivrogt ltbeangt
ltbean name=autowired class=diCliente autowire=byTypegt ltbeangt
ltbeansgt
Quando lidamos com este recurso nosso principal oponente eacute a ambiguumlidade Se na
listagem 9 houvesse mais um bean do tipo diDAOLivroTexto nos deparariacuteamos com um erro no momento em que o bean autowired fosse iniciado pelo container pois este natildeo
saberia qual bean injetar na propriedade daoLivro do bean autowired Uma das ferramentas que possuiacutemos para evitar estes problemas satildeo os modos
fornecidos pelo Spring para encontrar automaticamente as dependecircncias a serem
injetadas Na tabela 2 podemos ver todos estes modos cujos nomes correspondem ao valor a ser digitado no atributo autowire de um bean automaticamente injetado
Tabela 2 - Estrateacutegias de auto injeccedilatildeo de dependecircncias
Modo Descriccedilatildeo
no Comportamento default Desabilita a auto injeccedilatildeo de dependecircncias
para o bean byName O container iraacute buscar por dependecircncias que possuam o mesmo
nome que a propriedade a ser injetada Sendo assim na listagem 9 poderiacuteamos ter definido a auto injeccedilatildeo usando esta estrateacutegia que
funcionaria sem problemas Caso natildeo hajam beans com o mesmo
nome presentes entre as definiccedilotildees do container a exceccedilatildeo NoSuchBeanDefinitionException
byType A busca por dependecircncias seraacute por tipo O container iraacute buscar por
beans que sejam do mesmo tipo que a dependecircncia a ser injetada Havendo mais de uma possibilidade seraacute disparada uma exceccedilatildeo do tipo NoSuchBeanDefinitionException
constructor Eacute anaacuteloga agrave estrateacutegia byType A Diferenccedila eacute que seraacute feita a
injeccedilatildeo de dependecircncias a partir dos construtores do bean
8 O termo em inglecircs que poderia ser adotado ao inveacutes de auto injetado seria autowired
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
autodetect Seguindo esta estrateacutegia o container iraacute primeiro buscar executar a
injeccedilatildeo de dependecircncias por construtor Se for encontrado um
construtor default no bean o container passaraacute a adotar a estrateacutegia
byType
Deve-se usar a auto injeccedilatildeo de dependecircncias apenas em projetos de pequeno e meacutedio porte visto que trata-se de um processo bem menos preciso que a injeccedilatildeo expliacutecita
atraveacutes da definiccedilatildeo de propriedades e construtores Apesar do Spring se esforccedilar ao
maacuteximo para fazer a escolha correta podem haver situaccedilotildees nas quais uma injeccedilatildeo
incorreta seja feita Sendo assim seu uso normalmente eacute desencorajado em projetos maiores a natildeo ser que sejam adotadas regras riacutegidas na nomenclatura dos beans e sua
tipagem Caso queira diminuir ainda mais a quantidade de configuraccedilatildeo a ser digitada eacute
possiacutevel definir o comportamento de auto injeccedilatildeo default do container adicionando o
atributo default-autowire agrave tag beans com um dos valores presentes na tabela 2 Assim todos os beans nela contidos seguiratildeo a mesma poliacutetica
Para aumentar a precisatildeo da injeccedilatildeo automaacutetica podemos tambeacutem excluir
candidatos agrave injeccedilatildeo incluindo o atributo autowire-candidate com o valor false na tag bean do componente que queremos remover do processo de busca
Outra possibilidade interessante eacute dar preferecircncia a uma dependecircncia especiacutefica
adicionando o atributo primary com valo true agrave tag bean correspondente Em situaccedilotildees
nas quais ocorram mais de uma possibilidade de escolha este seraacute privilegiado no
processo ajudando assim a diminuir a possibilidade de ambiguumlidade no processo de auto injeccedilatildeo de dependecircncias
Poreacutem estas duas alternativas acabam por tornar mais complexo o processo de
criaccedilatildeo dos arquivos de configuraccedilatildeo Por esta razatildeo eacute uma boa praacutetica simplesmente natildeo
usar o autowiring em projetos de grande porte
Callbacks de Ciclo de Vida
Haacute situaccedilotildees nas quais natildeo basta apenas injetar as dependecircncias de um bean e
definir seu escopo Satildeo casos nos quais para que um bean esteja pronto para uso seja
necessaacuterio algum preacute-processamento interno antes que o mesmo seja fornecido ao objeto que o solicitou ao container Aleacutem disto haacute momentos nos quais eacute necessaacuterio que o
proacuteprio bean libere os recursos que usou durante sua existecircncia Spring nos oferece dois eventos que podemos customizar no ciclo de vida de nossos
beans inicializaccedilatildeo que eacute executado logo apoacutes todas as dependecircncias de um bean terem
sido injetadas e destruiccedilatildeo executado apenas apoacutes o container que gerencia o bean ter
sido destruiacutedo O callback de inicializaccedilatildeo pode ser adicionado ao bean de duas maneiras A
primeira delas eacute a implementaccedilatildeo da interface
orgspringframeworkbeansfactoryInitializingBean Esta conteacutem um uacutenico meacutetodo do
tipo chamado afterPropertiesSet() que dispara uma exceccedilatildeo geneacuterica Na listagem 10 haacute
um exemplo de sua implementaccedilatildeo Este procedimento natildeo eacute recomendado pois acopla o
bean ao Spring Framework violando assim um dos principais objetivos do framework que eacute justamente sua natildeo intrusatildeo nas classes do sistema
Listagem 10 Implementando callbacks de inicializaccedilatildeo e destruiccedilatildeo no coacutedigo fonte import orgspringframeworkbeansfactoryDisposableBean import orgspringframeworkbeansfactoryInitializingBean public class ClienteCallbacks implements InitializingBean DisposableBean public void afterPropertiesSet() throws Exception Systemoutprintln(Todas as dependecircncias injetadas)
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
public void destroy() throws Exception Systemoutprintln(Container destruido)
A outra opccedilatildeo eacute incluir na tag bean o atributo init-method O valor do atributo deve
ser o nome de um meacutetodo definido no bean que natildeo possua atributos e que pode ou natildeo
disparar alguma exceccedilatildeo Esta eacute a abordagem adequada visto que assim garantimos que
nosso bean natildeo esteja diretamente acoplado ao Spring Framework Jaacute o callback de destruiccedilatildeo tambeacutem pode ser adicionado usando basicamente os
mesmos procedimentos que adotamos par ao callback de inicializaccedilatildeo Podemos
implementar a interface DisposableBean que nos obrigaraacute a implementar o meacutetodo destroy() tal como fizemos na listagem 10 ou se preferirmos podemos tambeacutem
adicionar o atributo destroy-method agrave tag bean correspondente O valor do deste atributo deveraacute ser um meacutetodo que natildeo possua paracircmetros Como no caso do callback de
inicializaccedilatildeo esta eacute a abordagem favorita por evitar o acoplamento de nossas classes ao coacutedigo do Spring Framework
Haacute um detalhe que precisa ser mencionado o callback de destruiccedilatildeo natildeo eacute
executado jamais em beans cujo escopo seja prototype pois uma vez criado este bean natildeo estaacute mais sobre o poder do container de injeccedilatildeo de dependecircncias sendo assim eacute
impossiacutevel que o container venha a executar os meacutetodos de destruiccedilatildeo nestes beans
Alimentando o Container com Anotaccedilotildees Uma alternativa ao XML que apareceu pela primeira vez no Spring 20 eacute o uso das
anotaccedilotildees Trata-se de um caminho bastante interessante para os que gostam de ver suas configuraccedilotildees proacuteximas ao coacutedigo fonte ou sentem-se incomodados com a necessidade de se escrever documentos XML
O problema com as anotaccedilotildees eacute que elas aumentam o peso do Spring ao acoplar nossas classes ao Spring Framework Como veremos eacute possiacutevel diminuir este
acoplamento ao adotarmos anotaccedilotildees baseadas em JSRs poreacutem mesmo assim estaremos
aumentando o acoplamento de nossas classes o que natildeo ocorreria se estiveacutessemos adotando configuraccedilotildees puramente baseadas em XML Outro problema eacute que a
necessidade de se recompilar coacutedigo ao adicionarmos novos componentes ao nosso
sistema aumenta significativamente Poreacutem as anotaccedilotildees natildeo excluem completamente o XML Na realidade XML e
anotaccedilotildees convivem perfeitamente bem em um mesmo sistema Voltando ao nosso
sistema inicial uma versatildeo alternativa baseada em anotaccedilotildees precisaria de um arquivo de
configuraccedilatildeo tal como o exposto na listagem 11
Listagem 11 Configurando o container para trabalhar com anotaccedilotildees ltxml version=10 encoding=ISO-8859-1gt ltbeans xmlns=httpwwwspringframeworkorgschemabeans xmlnsxsi=httpwwww3org2001XMLSchema-instance xmlnscontext=httpwwwspringframeworkorgschemacontext xsischemaLocation=httpwwwspringframeworkorgschemabeans httpwwwspringframeworkorgschemabeansspring-beans-30xsd httpwwwspringframeworkorgschemacontext httpwwwspringframeworkorgschemacontextspring-context-30xsdgt ltcontextannotation-configgt ltcontextcomponent-scan base-package=dianotadosgt ltbean id=daoLivro class=diDAOLivroTexto scope=prototype primary=truegt ltproperty name=arquivo value=livrostxtgt ltbeangt ltbeansgt
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Como pode ser observado na listagem 11 ainda estou mapeando um bean usando XML Foi feito propositalmente para expor como as duas abordagens anotaccedilotildees e XML
convencional convivem perfeitamente lado a lado Comparando a listagem 11 com a listagem 2 observa-se a inclusatildeo de um novo namespace context Eacute fundamental que este
seja declarado para que o Spring possa trabalhar com anotaccedilotildees Haacute tambeacutem duas novas tags ltcontextannotation-configgt informa o container que
seratildeo usadas configuraccedilotildees baseadas em anotaccedilotildees aleacutem do XML convencional Outra tag
importante eacute ltcontextcomponent-scangt Esta instrui o container a no momento em que for inicializado varrer todas as classes contidas no pacote dianotados em busca dos beans a serem gerenciados pelo container
O leitor atento tambeacutem observaraacute a ausecircncia do bean cliente Nesta versatildeo
alternativa do nosso sistema este bean seraacute configurado usando apenas anotaccedilotildees Sendo
assim implementamos uma classe chamada ClienteComponente exposta na listagem 12 Esta classe expotildee praticamente todas as configuraccedilotildees que expusemos na seccedilatildeo dedicada
agrave configuraccedilatildeo baseada em XML Dado que os conceitos baacutesicos da injeccedilatildeo de dependecircncias foi dado na seccedilatildeo em
que tratamos da configuraccedilatildeo proveniente de documentos em formato XML nosso foco agora seraacute em expor os equivalentes daquela configuraccedilatildeo ao adotarmos o modelo de
configuraccedilotildees baseadas em anotaccedilotildees
Listagem 12 A classe ClienteComponente import diIDAOLivro import javaxannotationPostConstruct import javaxannotationPreDestroy import javaxannotationResource import orgspringframeworkcontextannotationScope import orgspringframeworkstereotypeComponent Scope(prototype) Component(clienteAnotado) public class ClienteComponente private IDAOLivro daoLivro public IDAOLivro getDaoLivro() return thisdaoLivro Resource(name=daoLivro) public void setDaoLivro(IDAOLivro dao) thisdaoLivro = dao PostConstruct public void init() Systemoutprintln(Fui construido E meu dao eacute + getDaoLivro()getClass()) PreDestroy public void destroy() Systemoutprintln(Meu container foi destruido)
Identificando beans com Component
Ao varrer o pacote dianotados o container iraacute buscar todas as classes que possuam
a anotaccedilatildeo Component Esta equivale agrave tag bean que vimos anteriormente Como boa praacutetica eacute interessante passar como paracircmetro para esta classe um valor do tipo string que
nomeie nosso bean Caso natildeo seja feito o container iraacute criar um nome interno para o
bean poreacutem este seria de pouca valia para noacutes pois um bean realmente uacutetil eacute aquele que
possamos usar e para usaacute-lo este precisa ser nomeado Pense nesta anotaccedilatildeo como a dica que enviamos ao container para que identifique
uma de nossas classes como um bean a ser gerenciado
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Definindo o escopo com Scope
A anotaccedilatildeo Scope eacute o equivalente ao atributo scope da tag bean Se omitido seraacute
adotado o escopo padratildeo do Spring que tal como jaacute mencionado eacute o Singleton Esta
anotaccedilatildeo recebe como paracircmetro o nome do escopo que iremos adotar Na listagem 12 soacute
para variar adotamos o escopo prototype
Definindo dependecircncias com Resource
Anotaccedilotildees tambeacutem possuem um relativo para a tag property No caso estamos
falando da anotaccedilatildeo Resource que deve ser aplicada sobre atributos ou setters de
nossas classes Este atributo recebe como paracircmetro o nome do bean que desejamos seja
injetado em nosso bean Eacute interessante observar que esta anotaccedilatildeo natildeo eacute nativa do Spring mas sim da JSR-
250 cujo objetivo eacute definir anotaccedilotildees para conceitos semacircnticos em comum presentes nas
plataformas Java SE e EE Sendo assim ao usarmos esta anotaccedilatildeo estamos na realidade
evitando mais uma ligaccedilatildeo direta com classes do Spring o que eacute uma praacutetica interessante
visto que no futuro caso seja necessaacuterio trocar o container de injeccedilatildeo de dependecircncias
esta tarefa se tornaraacute menos trabalhosa Na listagem 12 estamos instruindo o container a injetar o bean daoLivro no bean
clienteAnotado
Autowiring com Autowired ou Inject
Equivalente ao atributo autowired que vimos na configuraccedilatildeo baseada em XML
possuiacutemos as anotaccedilotildees Autowired e Inject Autowired eacute a anotaccedilatildeo provida pelo
Spring Sendo assim ao adotaacute-la devemos ter em mente que estamos incluindo uma dependecircncia direta ao Spring Framework em nosso coacutedigo fonte Jaacute a anotaccedilatildeo Inject
faz parte da JSR-330 que especifica o mecanismo de injeccedilatildeo de dependecircncia padratildeo para
a plataforma Java Sendo assim o uso de Inject eacute preferiacutevel ao de Autowired pois
assim estamos criando uma dependecircncia com um padratildeo Java e natildeo algo tatildeo especiacutefico
quanto o Spring Na listagem 13 podemos ver um exemplo da aplicaccedilatildeo de Autowired em mais
uma versatildeo de nosso bean cliente assim eacute possiacutevel expor mais uma diferenccedila entre
AutoWired e Inject No caso Autowired possui um atributo adicional chamado required que aceita um valor booleano Quando definido como true caso natildeo seja
encontrado o bean a ser injetado uma exceccedilatildeo seraacute disparada pelo container de injeccedilatildeo de
dependecircncias Esta opccedilatildeo eacute uacutetil quando a aplicaccedilatildeo estaacute em desenvolvimento pois permite aos
desenvolvedores encontrar problemas antes que o sistema entre em produccedilatildeo
Listagem 13 Usando Autowired import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowired import orgspringframeworkstereotypeComponent Component(clienteAnotadoAutowired) public class ClienteComponenteAutoWired Autowired(required=true) private IDAOLivro dao public IDAOLivro getDaoLivro() return dao public void setDaoLivro(IDAOLivro dao) thisdao = dao
Callbacks de inicializaccedilatildeo e destruiccedilatildeo com PostConstruct e PreDestroy
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Na listagem 12 podemos ver a aplicaccedilatildeo das anotaccedilotildees PostConstruct e
PreDestroy que equivalem aos atributos init-method e destroy-method que vimos na configuraccedilatildeo baseada em XML
Seu uso natildeo poderia ser mais simples inclua PostConstruct no meacutetodo sem
paracircmetros que deveraacute ser executado apoacutes ter sido feita a injeccedilatildeo de dependecircncias em seu
bean para identificar o callback de inicializaccedilatildeo e PreDestroy no meacutetodo sem
paracircmetros que deveraacute ser executado no momento em que o container de injeccedilatildeo de
dependecircncias for ser destruiacutedo
Quando o XML anula as anotaccedilotildees
Ao ser inicializado o container do Spring primeiro carrega as configuraccedilotildees
provenientes de anotaccedilotildees para em seguida processar as configuraccedilotildees em formato XML
Sendo assim eacute importante que o leitor saiba que caso um bean seja configurado
inicialmente usando anotaccedilotildees e este mesmo bean esteja especificado no formato XML as configuraccedilotildees no segundo formato anularatildeo a primeira
Este eacute um erro muito comum em times que tenham optado por trabalhar com os
dois formatos poreacutem pode ser visto tambeacutem como uma alternativa viaacutevel quando se deseja anular configuraccedilotildees em cima das quais natildeo possuiacutemos controle como por exemplo as que estatildeo presentes em classes jaacute compiladas presentes no classpath de nosso
sistema
Limitaccedilotildees das anotaccedilotildees
Atualmente configuraccedilotildees baseadas em anotaccedilotildees natildeo permitem que seja mapeado
mais de um bean para uma mesma classe tal como fizemos na listagem 4 Caso seja necessaacuterio que isto seja feito o desenvolvedor possui apenas duas alternativas ou mapeia
apenas um bean usando anotaccedilotildees para uma classe e o restante usando XML ou faz todo o trabalho usando apenas XML
Dentre as duas alternativas a segunda eacute uma melhor praacutetica visto que assim expotildee
para o time todas as variantes do bean para todos os membros da equipe de uma forma mais expliacutecita evitando assim problemas de comunicaccedilatildeo dentro do time
Outra limitaccedilatildeo das anotaccedilotildees eacute que elas natildeo nos permitem definir o valor de
atributos primitivos ou listas tal como podemos fazer facilmente no caso do XML
Configuraccedilatildeo baseada em Java (100 livre de XML) No Spring 30 foi introduzido um novo tipo de contexto de aplicaccedilatildeo chamado
AnnotationConfigApplicationContext que pela primeira vez possibilita ao desenvolvedor configurar um container de injeccedilatildeo de dependecircncias do Spring sem a presenccedila de
qualquer arquivo XML pois toda configuraccedilatildeo eacute feita via coacutedigo Trata-se de uma alternativa bastante poderosa que pode ser usada em situaccedilotildees nas
quais os beans gerenciados pelo container natildeo possam ser definidos apenas
declarativamente como fizemos usando apenas anotaccedilotildees ou XML Agora podemos
incluir loacutegica neste processo de uma maneira bastante simples Visto que todos os conceitos referentes ao processo de gerenciamento de beans jaacute
foi tratado nas seccedilotildees anteriores deste artigo iremos ver aqui apenas como mapear os beans usando este novo recurso de uma maneira raacutepida comparando-o com as maneiras anteriores
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
Apresentando Configuration e Bean
Antes de tratarmos da classe AnnotationConfigApplicationContext iremos ver o que
o alimenta no caso as anotaccedilotildees Configuration e Bean aplicadas a POJOs Na
listagem 14 podemos ver a aplicaccedilatildeo destas anotaccedilotildees
Listagem 14 Aplicando as anotaccedilotildees Configuration e Bean import diCliente import diDAOLivroSGBD import diDAOLivroTexto import diIDAOLivro import orgspringframeworkbeansfactoryannotationAutowire import orgspringframeworkcontextannotationBean import orgspringframeworkcontextannotationConfiguration Configuration public class BeanSource Bean(name=daoLivro) public IDAOLivro getDAOLivro() return new DAOLivroTexto() Bean(name=cliente) public Cliente getCliente() Cliente saida = new Cliente() saidasetDaoLivro(getDAOLivro()) return saida Bean(name=clienteSGBD) public Cliente getClienteSGBD() Cliente saida = new Cliente() saidasetDaoLivro(new DAOLivroSGBD()) return saida Bean(name=clienteAutowired autowire=AutowireBY_TYPE) public Cliente getClienteAutowired() return new Cliente()
Tabela 3 - Atributos de Bean
Atributo Descriccedilatildeo
name O nome dado ao bean que seraacute retornado autowire Qual poliacutetica de autowiring que seraacute adotada pelo container
Valores possiacuteveis AutowireBY_TYPE AutowireBY_NAME AutowireNO gt Desabilita o autowiring e eacute o valor default
initMethod Nome do meacutetodo que deveraacute ser invocado no bean apoacutes este ter
suas dependecircncias injetadas destroyMethod Nome do meacutetodo que deveraacute ser invocado quando o container que
gerencia o bean for destruiacutedo A classe presente na listagem 14 eacute o que chamamos de Configuration ou seja uma
classe anotada com Configuration e que possui funccedilotildees anotadas com a anotaccedilatildeo
Bean que produzem beans que seratildeo gerenciados pelo container de injeccedilatildeo de
dependecircncias do Spring Sendo assim para criar uma classe de configuraccedilatildeo tudo o que o desenvolvedor
precisa fazer eacute anotaacute-la com Configuration e em seguida implementar uma ou mais funccedilotildees anotadas com Bean cujos atributos encontram-se listados na tabela 3
Autowiring
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
A primeira impressatildeo que temos quando nos deparamos com este novo recurso eacute
que natildeo precisaremos mais da injeccedilatildeo automaacutetica de dependecircncias visto que estamos
manualmente criando nossos beans Felizmente isto natildeo eacute verdade Para ativar o
autowiring basta definir o valor do paracircmetro autowire com o valor AutowireBY_NAME ou AutowireBY_TYPE tal como exposto na tabela 3
Observando a listagem 14 vemos que o autowiring eacute aplicado no meacutetodo
getClienteAutowired() usando a estrateacutegia por tipo
Definindo o escopo Novamente aqui o padratildeo do Spring se aplica Se natildeo for definido explicitamente
qual o escopo do bean este seraacute interpretado como pertencente ao escopo singleton Para que o bean possua um escopo
Callbacks de Inicializaccedilatildeo e Destruiccedilatildeo
Tal como na configuraccedilatildeo baseada em XML como na configuraccedilatildeo baseada em
anotaccedilotildees tambeacutem podemos definir os callbacks de inicializaccedilatildeo e destruiccedilatildeo A
diferenccedila eacute que os definimos com os atributos initMethod e destroyMethod presentes na anotaccedilatildeo Bean Exatamente como nos casos anteriores eles devem conter o nome de
um meacutetodo que natildeo possua atributos presentes na classe do bean a ser retornado
Apresentando o container AnnotationConfigApplicationContext
A classe que possibilita a configuraccedilatildeo baseada em Java eacute
AnnotationConfigApplicationContext que se encontra no pacote orgspringframeworkcontextannotation Para usaacute-la no entanto eacute necessaacuterio adicionar
duas dependecircncias externas ao seu projeto No caso as bibliotecas CGLIB e ASM9 que satildeo usadas para manipular bytecode em tempo de execuccedilatildeo
Haacute dois modos de se alimentar as configuraccedilotildees de
AnnotationConfigApplicationContext O desenvolvedor pode criar uma nova instacircncia
desta classe passando uma uacutenica classe de configuraccedilatildeo ou um array de classes de
configuraccedilatildeo ou programaticamente As duas maneiras podem ser vistas na listagem 15
Listagem 15 Alimentando AnnotationConfigApplicationContext AnnotationConfigApplicationContext contexto = null Alimentando com uma uacutenica classe de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass) Alimentando com um array de classes de configuraccedilatildeo contexto = new AnnotationConfigApplicationContext(BeanSourceclass DataSourcesclass) Alimentando o context programaacuteticamente contexto = new AnnotationConfigApplicationContext() contextoregister(BeanSourceclass) apoacutes adicionar todas as classes ao contexto execute obrigatoacuteriamente o meacutetodo refresh() contextorefresh()
Conclusotildees Como pudemos ver o container de injeccedilatildeo do Spring eacute uma ferramenta bastante
rica que nos permite resolver de maneira elegante o problema do alto acoplamento em nossos sistemas Tal como dito na introduccedilatildeo eacute importante conhecer o conceito de
9 A biblioteca CGLIB (Code Generation Library) pode ser obtida em seu site oficial
httpcglibsourceforgenet Para este artigo foi usada a versatildeo 22 Jaacute a biblioteca ASM pode ser obtida
em httpasmow2org Usamos neste artigo a versatildeo 32
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software
Guia itexto Injeccedilatildeo de Dependecircncias com Spring Framework 3 httpdevkicoitextocombr
injeccedilatildeo de dependecircncias mesmo que o Spring jamais seja usado porque seu conhecimento torna explicita a principal causa de designs ruins de aplicaccedilatildeo
Poreacutem caso o Spring venha a ser adotado eacute importante que a sua natildeo intrusatildeo seja
mantida o maacuteximo possiacutevel pois caso contraacuterio podemos acabar voltando ao problema do
alto acoplamento Tal como exposto no artigo conseguimos manter esta leveza a partir da adoccedilatildeo de configuraccedilatildeo no formato XML ou Java e no caso das anotaccedilotildees adotando ao
maacuteximo possiacutevel apenas anotaccedilotildees que sejam parte de alguma JSR ao contraacuterio das que
fazem parte do core do Spring O mais interessante no entanto eacute a constataccedilatildeo do poder que o conceito de injeccedilatildeo
de dependecircncias possui Percebemos este poder ao constatar que apenas o que foi
exposto neste artigo fornece a base para todos os demais componentes do Spring Framework e seus derivados como Grails por exemplo
Referecircncias httpwwwspringframeworkorg Site oficial do Spring Framework httpstaticspringsourceorgspringdocs30xspring-framework-referencehtml -
Documentaccedilatildeo de referecircncia do Spring Framework 30 httpwwwobjectmentorcompublicationsdippdf - Artigo The Dependency
Injection Principle de Robert C Martin httpwwwmartinfowlercomarticlesinjectionhtml - Artigo Inversion of Control
Containers and the Dependency Injection pattern de Martin Fowler que cunhou o termo
Injeccedilatildeo de Dependecircncias
Henrique Lobo Weissmann (o Kico) (kicoloboitextonet) eacute consultor GroovyGrails
fundador do Grails Brasil e soacutecio da itexto Desenvolvimento de Projetos
(httpwwwitextocombr) que atua na criaccedilatildeo de projetos adotando software livre e muito
Grails Aleacutem disto em seu blog (httpdevkicoitextocombr) expotildee sua experiecircncia no
desenvolvimento de software