Spring Framework (2.0) Framework para Desenvolvimento de Aplicações em Java
Diego Pacheco Dez/2007
Apostila desenvolvida especialmente para a Crom Microsystems. Sua cópia ou reprodução é livre.
Sobre o Autor
Diego Pacheco Técnico em Processamento de Dados e graduando em Ciências da Computação(7º sem.) na Ulbra. Já trabalhou com desenvolvimento de software em VB, ASP, .NET e PHP. Atualmente é Arquiteto de Software, certificado pela Sun, atuo desenvolvendo soluções corporativas em arquitetura JEE, provendo coaching/mentoring em software e processo de desenvolvimento de software. Gosto muito de música, tocar guitarra, jogar PSP, Bloggar, Ler e principalmente as incríveis histórias do Conan. Mantenho o blog < http://diego-pacheco.blogspot.com/> a mais de 3 anos.
Spring Framework – Framework para Desenvolvimento de Aplicações Java
Sumário 1. Introdução .................................................................................................................... 1-1 Objetivos ...................................................................................................................................1-2 Conceitos Básicos .................................................................................................................1-3 Cenários de uso ....................................................................................................................1-7 Portifólio ...............................................................................................................................1-10 Download ..............................................................................................................................1-12 Estrutura de Diretórios ..................................................................................................1-13 Exercícios ..............................................................................................................................1-15 Espaço para anotações ....................................................................................................1-16
2. Container IoC .............................................................................................................. 2-1 Objetivos ...................................................................................................................................2-2 IoC – Inversion of control ...............................................................................................2-3 Registrando Beans .............................................................................................................2-13 Singletons e lazy Initialization .................................................................................2-15 Lazy Initialization ...........................................................................................................2-18 Scopos dos Beans ................................................................................................................2-20 Criando seu próprio scope ............................................................................................2-23 Injeção via setter.................................................................................................................2-27 Injeção via construtor ......................................................................................................2-29 Injeção de coleções .............................................................................................................2-31 Injeção entre beans colaboradores ............................................................................2-36 Instanciando o contexto Web .......................................................................................2-40 Exercícios ..............................................................................................................................2-42 Espaço para anotações ....................................................................................................2-43
3. Manipulação de Beans .......................................................................................... 3-1 Objetivos ...................................................................................................................................3-2 Resource Loaders .................................................................................................................3-3 Init-Metohd e InitializingBean ...................................................................................3-4 Herança de Definições ......................................................................................................3-7 Validação ..............................................................................................................................3-10 Bean Wrapper......................................................................................................................3-13 BeanPostProcessors ............................................................................................................3-17 Diego Pacheco – http://diego-pacheco.blogspot.com
I
Spring Framework – Framework para desenvolvimento de aplicações Java
BeanFactoryPostProcessors ............................................................................................3-21 Property Editors .................................................................................................................3-25 Eventos ....................................................................................................................................3-30 PropertyPlaceholderConfigurer .................................................................................3-33 SingletonBeanFactoryLocator ......................................................................................3-36 Internacionalização .........................................................................................................3-40 Exercicios ..............................................................................................................................3-44 Espaço para anotações ....................................................................................................3-45
Diego Pacheco – http://diego-pacheco.blogspot.com
II
Spring Framework – Framework para desenvolvimento de aplicações Java
4. Persistência .................................................................................................................. 4-1 Objetivos ...................................................................................................................................4-2 Hierarquia de Exceptions ...............................................................................................4-3 Acesso a dados usando JDBC ........................................................................................4-5 Trabalhando com DataSources ....................................................................................4-5 Trabalhando com JDBCTemplate ..............................................................................4-7 Session Factory Bean ........................................................................................................4-11 Hibernate Template..........................................................................................................4-13 Transações Declarativas .................................................................................................4-18 Exercícios ..............................................................................................................................4-22 Espaço para anotações ....................................................................................................4-23
5. Facilitadores ................................................................................................................ 5-1 Objetivos ...................................................................................................................................5-2 Envio de E-mails ................................................................................................................5-3 Agendamento de tarefas com JDK Task .................................................................5-10 @Aspect Support .................................................................................................................5-16 Testing Support ...................................................................................................................5-23 AbstractDependencyInjectionSpringContextTests ..............................................5-24 AbstractAnnotationAwareTransactionalTests .....................................................5-27 AbstractTransactionalDataSourceSpringContextTests.....................................5-28 Remoting com RMI ...........................................................................................................5-29 Exercícios ..............................................................................................................................5-34 Espaço para anotações ....................................................................................................5-35
Diego Pacheco – http://diego-pacheco.blogspot.com
III
Spring Framework – Framework para Desenvolvimento de Aplicações Java
1. Introdução
Diego Pacheco – http://diego-pacheco.blogspot.com
Spring Framework – Framework para desenvolvimento de aplicações java
Objetivos •
Conhecer os conceitos básicos;
•
Conhecer os principais cenários de uso;
•
Prover uma visão de todo o portifólio do Spring;
•
Saber onde baixar o Spring;
•
Conhecer a estrutura de diretórios dos fontes.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-2
Spring Framework – Framework para desenvolvimento de aplicações java
Conceitos Básicos
Spring framework, garanto a você que não é nenhum produto de limpeza, até pode parecer pelo nome, mas não é. Spring é um dos frameworks líderes do mercado full-stack Java/JEE. Esse framework é mantido pela empresa Interface21 que tem como presidente, Rod Johnson, o criador do Spring que é simplesmente uma das maiores autoridades em Java. Spring prove diversos benefícios para muitos projetos, aumentando a produtividade de desenvolvimento e a performance em tempo de runtime em quanto ao mesmo tempo prove uma cobertura para testes e muita qualidade para a aplicação. O Spring prove soluções light-weight para construções de aplicações corporativas. Enquanto ainda suporta e prove a possibilidade de se usar: transações declarativas, acesso remoto através de RMI ou Web Services e muitas opções para persistência de dados. O Spring prove também uma solução completa MVC Framework e maneiras transparentes e elegantes para integração de AOP ao seu software. Esse framework é extremamente modular, assim você pode usar somente as partes que lhe interessam. É possível usar IoC com Struts ou por exemplo, você pode optar por usar somente a camada de integração com Hibernate ou a camada de abstração para JDBC. Desenhado para não ser intrusivo, utilizando apenas ele mesmo ou o mínimo de dependências para suas funcionalidades. Esse framework foi muito bem dividido, e isso pode ser observado com clareza na figura a baixo.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-3
Spring Framework – Framework para desenvolvimento de aplicações java
Figura 1.1 Visão Geral
Utilizando o Spring você já terá um ganho excelente em qualidade de software em termos de design patterns, utilizando ele praticamente anula o uso de patterns como Factory e ServiceLocator. Todo Objeto componente de sua aplicação é por default para o Spring um singleton, assim favorecendo as boas práticas e a performance. A Empresa Interface21 e com certeza o Spring tem como missão os seguintes valores: •
J2EE Deveria ser muito fácil de usar
•
É melhor programar para interfaces do que para classes, Spring reduz o custo e a complexidade de usar interfaces para zero.
•
JavaBeans oferece uma maneira excelente para configurar uma aplicação.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-4
Spring Framework – Framework para desenvolvimento de aplicações java
•
O Design OO é mais importante do que qualquer tecnologia de implementação como, por exemplo, J2EE.
•
Exception checadas são mal utilizadas no Java. Um framework não deveria forçar você a capturar exceptions que você não está apto a se recuperar.
•
Testabilidade é essencial, o Spring ajuda você a testar seu código mais facilmente.
•
O Spring precisa ser prazeroso para quem desenvolve usando ele.
•
O Código de sua aplicação deveria não depender da API do Spring.
•
O Spring não compete com as boas soluções existentes, mas prove integração dessas tecnologias, como exemplo o Hibernate, o Spring não pretende desenvolver outra, apenas integrá-la e prover facilidades.
Algumas das funcionalidades do core do Spring são: O Mais completo lightweight container: Prove centralização, automação de configuração e escrita para seus objetos de negocio. É um container não intrusivo, capaz de suportar sistemas complexos de um conjunto de componentes (POJO) de baixo acoplamento, consistência e transparência. O Container traz agilidade ao desenvolvimento e também testabilidade e uma alta escalabilidade, permitindo que os componentes de software possam ser desenvolvidos e testados isoladamente. Pode ser utilizado em qualquer ambiente de desenvolvimento J2SE ou J2EE. Uma camada comum de abstração para Transações: Permite gerenciamento transacional plugável com uma marcação transacional fácil, assim evitando pequenos problemas de baixo nível. Estratégias para JTA e para um único JDBC DataSource são incluídos. Em contraste com a JTA e o EJB CMT, as transações do spring não estão disponíveis só em ambientes J2EE, é possível utilizar em ambiente J2SE também. Uma Camada de Abstração para JDBC: Prove uma hierarquia de exceptions a partir de SQLException de maneira totalmente significativa. Simplifica o tratamento de erros, e diminuiu muito a quantidade de código a ser escrito. Nunca mais será necessário escrever um bloco finaly para usar JDBC. Integração com Toplink, Hibernate, JDO, and iBATIS SQL Maps: Em termos de resource holders, suporte a implementações de DAOs e estratégias transacionais. Existe um suporte de primeira classe para Hibernate com muitas facilidades providas pelo mecanismo de IoC.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-5
Spring Framework – Framework para desenvolvimento de aplicações java
Funcionalidade AOP: Totalmente integrado com o gerenciamento configuracional do Spring, você pode utilizar AOP com qualquer objeto gerenciado pelo Spring, adicionando aspectos em gerenciamento transacional, por exemplo. Com Spring é possível ter transações declarativas sem EJB e até mesmo sem JTA, caso você esteja utilizando um único banco de dados em um servidor tomcat, por exemplo.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-6
Spring Framework – Framework para desenvolvimento de aplicações java
Cenários de uso
Podemos utilizar Spring nos mais diversos cenários, desde um simples applet até mesmo nas mais complexas aplicações corporativas. Um exemplo típico de uso do Spring em uma aplicação completa Java EE onde teremos:
Figura 1.2 Cenário completo de uso em JEE.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-7
Spring Framework – Framework para desenvolvimento de aplicações java
Uma camada de validações de formulários, soluções em upload de arquivos, bind de objetos de domínio e claro, uma integração com JSP, Velocity, XSLT, PDF e Excel. Após isso o contexto web, gerenciado pelo Spring e utilizando o Spring MVC. No cerne das aplicações o contexto principal do Spring com o container IoC e algumas funcionalidades, como envio de e-mails e acessos remotos através de RMI, SOAP, Burlap, etc. Seguindo da camada de regras de negócio, onde temos facilidades com o módulo de AOP e a integração com o módulo de ORM, chegando finalmente na camada de persistência através do suporte rico ao Hibernate ou via JDBC. Tudo isso rodando em um container JSP/Servlet como o Tomcat ou Jetty. No caso de sua aplicação precisar fazer algum acesso remoto o Spring prove isso de maneira transparente e elegante.
Figura 1.3 Cenário remoto. É normal uma aplicação necessitar fazer acesso remoto a alguma outra aplicação ou serviço, nesse cenário é interessante usar spring também, pois além de facilitar a abstrair muito a complexidade de fazer esses acessos, você pode usar os seus componentes que já estão sendo gerenciados pelo spring obtendo assim uma máxima integração entre seus componentes de negócios e os componentes remotos.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-8
Spring Framework – Framework para desenvolvimento de aplicações java
Podemos usar Spring também se for necessário fazer integração com EJB, é possível utilizar os recursos da camada de acesso e abstração de EJB.
Figura 1.4 Cenário EJB. O Spring permite você reutilizar seus pojos existentes e empacotados em Stateless Session Beans, para serem usados em aplicações web escaláveis, que precisam de segurança declarativa.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-9
Spring Framework – Framework para desenvolvimento de aplicações java
Portifólio
O Spring possui um portifólio muito abrangente, que é composto por uma série de projetos “Spring...”, podemos dizer que é um ecossistema muito diversificado, composto pelos seguintes projetos: Spring Framework: Principal projeto do portifólio da Interface21, esse é o framework base de todos os outros. Contém recursos como container IoC, suporte a Hibernate, jdbc, aop, integração com os principais frameworks do mercado. Spring Web Flow: framework web baseado em fluxos, prove a facilidade de desenvolver modelos de ações dos usuários em alto nível de abstração. É possível agrupar dois fluxos de controle e formar um modulo da junção dos dois. Spring Web Services: Facilita o desenvolvimento de services SOAP, permitindo a criação de web services flexíveis, com suporte a segurança WS, permitindo ecriptação, decriptação. Possui integração com segurança ACGI. Além disso, o Spring Web Services faz as boas práticas serem fáceis, ajudando você desenvolver com baixo acoplamento entre o contrato e a implementação. Spring Acegi: Acegi é uma solução flexível e poderosa para segurança de aplicações Java. Dentre as principais facilidades estão: autenticação, autorização, acesso baseado em instância, canal de segurança e capacidades de detecção humana. Utiliza o contexto do Spring para suas configurações, configuração de forma não intrusiva, utilizando filters. Spring LDAP: Ajuda nas operações LDAP, baseada no pattern Spring’s JdbcTemplate. O Framework alivia o desenvolvedor de abrir e fechar contextos, fazer loopings através de NamingEnumerations, encoding/deconding de valores e filtros.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-10
Spring Framework – Framework para desenvolvimento de aplicações java
Spring Rich Client: Framework para desenvolvimento de aplicações Rich Client, é uma boa solução para construções de aplicações swing de maneira rápida e de qualidade. Possuí um conjunto rico de UI Factories, o foco desse projeto e prover boas práticas de maneira viável para o desenvolvimento swing, possui integração com Jgoodies e layout managers ricos como o TableLayout. Spring IDE para eclipse: Plugin para o ide eclipse com facilidades para o uso de Spring. Preove auto complete para os xmls de configuração do Spring, módulo visual para o Spring Web Flow, negação entre os beans do Spring, e visualização de recursos AOP. Spring BeanDoc: É uma ferramenta que facilita a documentação e desenho gráfico dos beans do contexto do Spring. Desenhado para ser flexível e simples de usar. BeanDoc pode facilitar a visualização das camadas da aplicação e como os objetos interagem. Pode ser configurado por uma task ant. Spring OSGI: Facilita a criação de aplicações Spring que irão rodar em um framework OSGI, uma aplicação escrita dessa forma tem uma separação melhor entre os módulos, com isso ganha a habilitada de remover, adicionar, atualizar os módulos em tempo de execução. Spring JavaConfig: Projeto que prove algumas anotações para efetuar o mapeamento de pojos com menos configurações em XML. Esse projeto não substitui completamente o uso de XML, mas consegue reduzir bastante em algumas funcionalidades de injeção. Spring.NET: Implementação do Core do Spring, com o seu container de IoC, só que para a plataforma da Microsoft .NET, esse projeto não tem todas as funcionalidades do Spring para Java, mas conta com muitos recursos do Spring feitos em Java como AOP, gerenciamento transacional e integração com Web. Spring Extensions: Projeto que é uma coleção de ferramentas para estender as funcionalidades do Spring framework, prove facilidade de integrar o Spring com outros frameworks. Dentre os tantos frameworks que são integrados com esse projeto estão: ant, Lucene, cache declarativo com EHCache, Drools, Jakarta Commons, engines de tamplates como Velocity, jBPM, etc. Spring Batch: Prove suporte para execução de tarefas muito longas. Suporte a programas batch os quais processam um volume muito grande de informações de um banco de dados. Com suporte a agendamento automático ou manual após falhas, esse projeto promove suporte de execuções batch para ambientes corporativos.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-11
Spring Framework – Framework para desenvolvimento de aplicações java
Download O Spring Framework pode ser obtido através do site: http://www.springframework.org/download existe a possibilidade de baixar somente o framework ou baixar o framework e suas dependências. A Versão do Spring que será usada nessa apostila é a 2.0.6 , mas muitos itens descritos aqui são válido também para a versão 1.2.x do framework. O Spring framework necessita apenas uma versão do 1.5 JDK ou superior, não é necessário criar variáveis de ambiente para o Spring. O Spring usa um conjunto de frameworks muito grande, então é recomendado fazer download da versão full com dependência que tem por volta de 60Mb.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-12
Spring Framework – Framework para desenvolvimento de aplicações java
Estrutura de Diretórios
Agora será detalhada a estrutura de diretórios da distribuição do Spring framework. Ao descompactar os binários do Spring teremos uma estrutura de diretórios da seguinte forma:
Figura 1.4 Estrutura de Diretórios da distribuição do Spring.
aspectj: Fontes dos testes dos artefatos que utilizam aspectj, aqui temos alguns artefatos de transação feitos em aspectJ. dist: Distribuição binárias dos fontes do Spring, aqui você encontrará os jars do Spring, bem como todos os jars de todos os módulos separados. docs: Contem toda a documentação do Spring, nessa você irá encontrar o JavaDoc, Reference Guide, documentação das taglibs do Spring. lib: Nesse diretório estão todas as dependências diretas e indiretas do Spring framework, aqui você encontrar jars de diversos frameworks, como por exemplo hibernate, struts, junit, ant.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-13
Spring Framework – Framework para desenvolvimento de aplicações java
mock: Fontes do mecanismo de mock que são utilizados para testes unitários, nesse diretório você encontra os fontes dos testes dos mocks também. samples: Nesse diretório existem diversos exemplos de mini-aplicações utilizando o Spring Framework, como por exemplo a Petclinic que é uma clinica de animais. src: Contém todos os fontes do Spring framework, caso você precise desses fontes para debugar o comportamento de algum código do Spring. test: Nesse diretório você encontrará todos os fontes dos testes realizados com o Spring, é útil para aprender como utilizar algumas classes do Spring. tiger: Todos os fontes que utilizam recursos somente do Java 5.0 estão nesse diretório, como por exemplo, annotations.
Dois arquivos que estão soltos no diretório principal e são interessantes são o changelog.txt e o readme.txt. No arquivo changelog contém todas as mudanças dessa versão do Spring como, por exemplo: quais são as novas features e quais foram os bugs corrigidos. No arquivo readme nós temos a definição de cada modulo do Spring com suas dependências, isso é muito útil se você deseja utilizar somente alguns módulos do Spring e precisa saber as dependências.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-14
Spring Framework – Framework para desenvolvimento de aplicações java
Exercícios
1) Defina com suas palavras qual a utilidade do Spring Framework. 2) Cite três vantagens de se usar Spring framework. 3) Diga um cenário em que poderíamos utilizar Spring. 4) Diga uma das utilidades do arquivo readme.txt.
Diego Pacheco – http://diego-pacheco.blogspot.com
1-15
Spring Framework – Framework para desenvolvimento de aplicações java
Espaço para anotações
Diego Pacheco – http://diego-pacheco.blogspot.com
1-16
Spring Framework – Framework para Desenvolvimento de Aplicações Java
2. Container IoC
Diego Pacheco – http://diego-pacheco.blogspot.com
Spring Framework – Framework para desenvolvimento de aplicações java
Objetivos
•
Conhecer o conceito de IoC;
•
Saber utilizar Lazy initialization e Singletons;
•
Conhecer os escopos dos Beans;
•
Saber registrar beans no container do Spring;
•
Saber fazer injeções com setters e construtores;
•
Saber fazer injeções com coleções;
•
Saber fazer injeção entre beans colaboradores;
•
Saber instanciar o contexto do Spring.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-2
Spring Framework – Framework para desenvolvimento de aplicações java
IoC – Inversion of control
Com a grande demanda de desenvolvimento para o Java corporativo (JEE), surgiu um problema comum, como ligar a camada de acesso a dados com a camada de regra de negócio e por ventura a camada de apresentação? Uma solução é um container de Ioc que também é chamada de Dependency Injection(DI), o Spring framework possui um container de Ioc leve e implementa o pattern de setter injection. Esse container trabalha com serviços definidos pelo programador. Serviço é um componente de software que foi projetado para ser reutilizado em muitos lugares sem a necessidade de alteração de código, é possível alterar o seu comportamento estendendo-o de alguma forma. A Idéia principal da injeção de dependências é separar os Objetos e principalmente o objeto que usa um outro objeto não instanciar diretamente esse objeto. Sendo assim, a principal vantagem da Dependency Injection é separar uma interface de sua implementação concreta. São dois tipos de injeção que o Spring utiliza em seu container de Ioc, veja: Setter Injection: Nesse tipo de injeção de dependências se utiliza de métodos setters baseados em propriedades e padrões de getters/setters da Sun. Você não precisa ter a propriedade de fato em seu serviço, mas o padrão de nomenclatura deve estar correto. Constructor Injection: Nesse tipo de injeção de dependências é utilizado o construtor da própria classe para fazer as injeções necessárias. Esse construtor pode ter quantos parâmetros forem necessários. Principais vantagens do uso de IoC do Spring: •
Desacoplamento
•
Visão fácil de dependência
•
Facilidade para testes
•
Possibilita escrever aplicações para terceiros (fora do seu controle) Para fixar melhor esse conceito considere o seguinte exemplo pratico: Imagine
que um Autor escreveu muitos livros, então considere os seguintes pojos: Diego Pacheco – http://diego-pacheco.blogspot.com
2-3
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.bad; import java.util.List; public class Autor { private String nome; private List livros; public Autor() {} public Autor(String nome) { super(); this.nome = nome; } public void listarPorNome(){ Listar l = new Listar(); List ret = l.list(nome); System.out.println( (ret.size()==0) ? "NRE" : ret ); } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List getLivros() { return livros; } public void setLivros(List livros) { this.livros = livros; } }
Código 2.1 Autor.java
Diego Pacheco – http://diego-pacheco.blogspot.com
2-4
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.bad; public class Livro {
private private private private
Autor autor; String titulo; String editora; int ano;
public Livro() {} public Livro(Autor autor, String titulo, String editora, int ano) { super(); this.autor = autor; this.titulo = titulo; this.editora = editora; this.ano = ano; } public Autor getAutor() { return autor; } public void setAutor(Autor autor) { this.autor = autor; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public String getEditora() { return editora; } public void setEditora(String editora) { this.editora = editora; } public int getAno() { return ano; } public void setAno(int ano) { this.ano = ano; } @Override public String toString() { return "titulo: " + titulo + " editor: " + editora + " ano: " + ano; } }
Código 2.2 Livro.java Diego Pacheco – http://diego-pacheco.blogspot.com
2-5
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.bad; import java.util.ArrayList; import java.util.List; public class Listar { public List list(String nome){ Autor a = new Autor("Diego Pacheco"); List livros = new ArrayList(); livros.add(new Livro(a,"Livro da Vida","Do Livro",2000)); livros.add(new Livro(a,"Spring for Dummies","O'really",2001)); livros.add(new Livro(a,"Bit ou não","Variados Editora",2002));
List achados = new ArrayList(); for(Livro l: livros){ if (l.getAutor().getNome().equals(nome)) achados.add(l); } return achados; } }
Código 2.3 Listar.java
package com.targettrust.spring.bad; public class MainTest { public static void main(String[] args) { Autor autor = new Autor("Rod"); autor.listarPorNome(); autor.setNome("Diego Pacheco"); autor.listarPorNome(); } }
Código 2.4 MainTest.java
Diego Pacheco – http://diego-pacheco.blogspot.com
2-6
Spring Framework – Framework para desenvolvimento de aplicações java
Nós temos os seguintes objetos: Autor, Livro, Listar e MainTest. Nesse exemplo um Autor pode ter vários livros por isso dentro do Pojo de Autor temos List e a classe Listar se encarrega de armazenar os livros e autores e prover uma procura sobre esses dados. Como vocês devem ter percebido o pojo Autor contém um método chamado: listarPorNome que instância esse objeto Listar e procura pelos livros do autor. Esse exemplo por mais simplório, serve para demonstrar que existe um forte acoplamento entre o pojo Autor e a classe que lista os Livros por Autor, outro grande problema nesse exemplo é que não existem interfaces. O que aconteceria se um Autor pudesse ter outras coisas além de livros como, por exemplo: artigos, co-autorias, vídeos? Nesse caso essa mudança iria implicar em um refactoring muito grande nessas classes, mas como poderíamos resolver esse problema?
Diego Pacheco – http://diego-pacheco.blogspot.com
2-7
Spring Framework – Framework para desenvolvimento de aplicações java
Solução: Criar um interface Publicável e o Livro irá implementar essa classe, no pojo de Autor mude de uma lista de Livros para uma List de Publicáveis, assim criamos a possibilidade de um Autor ter diversos itens em seu portifólio como, por exemplo: Livros, Artigos, Co-autuações. Para resolver o problema de forma de armazenamento e procura de livros, foi criada a interface Listavel e a classe Listar implementa essa interface, agora podemos criar outra classe que faça acesso à base de dados, claro que esse classe deve implementar Listavel. No pojo do Autor precisamos colocar um atributo Listavel e através desse atributo que vamos acessar os dados. Essas novas classes iram ficar conforme os fontes a baixo. package com.targettrust.spring.bad.ok; import java.util.List; public class Autor { private String nome; private List publicaveis; private Listavel list; public Autor() {} public Autor(String nome) { super(); this.nome = nome; } public void listarPorNome(){ List ret = list.list(nome); System.out.println( (ret.size()==0) ? "NRE" : ret ); } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List getPublicaveis() { return publicaveis; } public void setPublicaveis(List publicaveis) { this.publicaveis = publicaveis; } public Listavel getList() { return list; } public void setList(Listavel list) { this.list = list; } }
Código 2.5 Autor.java Diego Pacheco – http://diego-pacheco.blogspot.com
2-8
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.bad.ok; public class Livro implements Publicavel{ private private private private
Autor autor; String titulo; String editora; int ano;
public Livro() {} public Livro(Autor autor, String titulo, String editora, int ano) { super(); this.autor = autor; this.titulo = titulo; this.editora = editora; this.ano = ano; } @Override public String getNome() { return getTitulo(); } @Override public String getTipo() { return "Livro"; } public String getAutor() { return autor.getNome(); } public void setAutor(Autor autor) { this.autor = autor; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public String getEditora() { return editora; } public void setEditora(String editora) { this.editora = editora; } public int getAno() { return ano; } public void setAno(int ano) { this.ano = ano; } @Override
Diego Pacheco – http://diego-pacheco.blogspot.com
2-9
Spring Framework – Framework para desenvolvimento de aplicações java
public String toString() { return "titulo: " + titulo + " editor: " + editora + " ano: " + ano; } }
Código 2.6 Livro.java package com.targettrust.spring.bad.ok; public interface Publicavel { public String getAutor(); public String getNome(); public String getTipo(); }
Código 2.7 Publicavel.java package com.targettrust.spring.bad.ok; import java.util.List; public interface Listavel { public List list(String nome); }
Código 2.8 Listavel.java
Diego Pacheco – http://diego-pacheco.blogspot.com
2-10
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.bad.ok; import java.util.ArrayList; import java.util.List; public class Listar implements Listavel{ public List list(String nome) { Autor a = new Autor("Diego Pacheco"); List publicaveis = new ArrayList(); publicaveis.add(new Livro(a,"Livro da Vida","Do Livro",2000)); publicaveis.add(new Livro(a,"Spring for Dummies","O'really",2001)); publicaveis.add(new Livro(a,"Bit ou não","Variados Editora",2002)); List achados = new ArrayList(); for(Publicavel p: publicaveis){ if (p.getAutor().equals(nome)) achados.add(p); } return achados; } }
Código 2.9 Listar.java package com.targettrust.spring.bad.ok; public class MainTest { public static void main(String[] args) { Autor autor = new Autor(); autor.setList(new Listar()); autor.setNome("Rod"); autor.listarPorNome(); autor.setNome("Diego Pacheco"); autor.listarPorNome(); } }
Código 2.10 MainTest.java
Diego Pacheco – http://diego-pacheco.blogspot.com
2-11
Spring Framework – Framework para desenvolvimento de aplicações java
Nesse exemplo conseguimos resolver os problemas citados acima, mas utilizamos a IoC “na mão”, ou seja, nós mesmos injetamos as dependências, a solução é boa, mas isso em um sistema grande seria muito custoso de se fazer, nesse ponto entra o container de IoC do Spring. O Container possibilita de maneira fácil e simples a injeção dessas dependências e reduz o custo de se trabalhar com essas interfaces quase à zero.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-12
Spring Framework – Framework para desenvolvimento de aplicações java
Registrando Beans
Agora vamos ver como registrar essas classes no contexto do Spring. Esse registro é muito simples, ele consiste em apontar para uma classe Java no seu classpath e dar um id a esse bean. Existem outras configurações que podemos fazer sobre esses beans, mas vamos começar mostrando como declarar um bean no Spring.
Código XML 2.1 Spring-beans.xml Para recuperarmos esse bean do Contexto do Spring, precisamos instanciar um contexto do Spring e solicitar o bean apartir do ID para o contexto, conforme exemplo a baixo. package com.targettrust.spring.primeiro; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/primeiro/Springbeans.xml"); Object bean = bf.getBean("autor"); System.out.println("Autor: " + bean); } }
Código 2.11 Obtendo um bean do Spring
Diego Pacheco – http://diego-pacheco.blogspot.com
2-13
Spring Framework – Framework para desenvolvimento de aplicações java
A BeanFactory é uma interface Java que representa o Container Ioc, essa BeanFactory
precisa
ser instanciada,
nesse
exemplo
foi
usado
a
factory
ClassPathXmlApplicationContext que é uma factory que leva em consideração xmls de configurações que estão no classpath. Existem várias factories no Spring, uma para cada situação, por exemplo, existe uma factory que é utilizada para subir o contexto do Spring em um ambiente Servlet. Após a inicialização do contexto do Spring podemos utilizar o método getBean para recuperar um bean do Spring, nesse exemplo estamos passando o ID do bean que foi o mesmo que registramos no XML: Spring-beans.xml Outra forma de criarmos a BeanFactory seria utilizar um ClassPathResource que aponta para o Xml dos beans e depois utilizar a factory XmlBeanFactory. Conforme o exemplo de código a baixo. ClassPathResource resource = new ClassPathResource("/com/targettrust/spring/primeiro/Spring-beans.xml"); BeanFactory bf = new XmlBeanFactory(resource);
Código 2.12 outra bean factory É possível registrar um Bean no contexto do Spring programaticamente, para isso é necessário utilizar um objeto BeanDefinition que é o objeto que configura o bean no Spring. BeanDefinition beanDefinition = new RootBeanDefinition(Livro.class, RootBeanDefinition.AUTOWIRE_NO); ((BeanDefinitionRegistry)bf).registerBeanDefinition("livro", beanDefinition); Object beanOutro = bf.getBean("livro"); System.out.println("Livro: " + beanOutro);
Código 2.13 Registra um bean programaticamente
Diego Pacheco – http://diego-pacheco.blogspot.com
2-14
Spring Framework – Framework para desenvolvimento de aplicações java
Singletons e lazy Initialization
Para aumentar a performance de sua aplicação com qualidade e aplicando design patterns o Spring por default transforma qualquer bean registrado nele em um singleton. Singleton é um padrão de projeto (Design Pattern) que consiste em manter apenas uma instância de um determinado objeto por classloader. É um pattern muito aplicado para conexões com banco de dados, por exemplo. Podemos ver isso através do seguinte teste. package com.targettrust.spring.singleton; import java.util.ArrayList; import java.util.List; public class Uf { private String nome; private String sigla; private List ufs; public Uf() { System.out.println("Inicio do processamento dos estados..."); initUfs(); } private Uf(String nome, String sigla) { this.nome = nome; this.sigla = sigla; } private void initUfs() { ufs = new ArrayList(); ufs.add(new Uf("Acre","AC")); ufs.add(new Uf("Alagoas","AL")); ufs.add(new Uf("Amapá","AP")); ufs.add(new Uf("Amazonas","AM")); ufs.add(new Uf("Bahia","BA")); ufs.add(new Uf("Ceará","CE")); ufs.add(new Uf("Distrito Federal","DF")); ufs.add(new Uf("Goiás","GO")); ufs.add(new Uf("Espírito Santo","ES")); ufs.add(new Uf("Maranhão","MA")); ufs.add(new Uf("Mato Grosso","MT")); ufs.add(new Uf("Mato Grosso do Sul","MS")); ufs.add(new Uf("Minas Gerais","MG")); ufs.add(new Uf("Pará","PA")); ufs.add(new Uf("Paraiba","PB")); ufs.add(new Uf("Paraná","PR")); ufs.add(new Uf("Pernambuco","PE")); ufs.add(new Uf("Piauí","PI")); ufs.add(new Uf("Rio de Janeiro","RJ")); ufs.add(new Uf("Rio Grande do Norte","RN")); ufs.add(new Uf("Rio Grande do Norte","RS")); ufs.add(new Uf("Rondônia","RO"));
Diego Pacheco – http://diego-pacheco.blogspot.com
2-15
Spring Framework – Framework para desenvolvimento de aplicações java
ufs.add(new ufs.add(new ufs.add(new ufs.add(new ufs.add(new
Uf("Rorâima","RR")); Uf("São Paulo","SP")); Uf("Santa Catarina","SC")); Uf("Sergipe","SE")); Uf("Tocantins","TO"));
} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getSigla() { return sigla; } public void setSigla(String sigla) { this.sigla = sigla; } public List getUfsBrazil(){ return ufs; } public void showInstance(){ System.out.println(super.toString()); } public String toString() { return sigla; } }
Código 2.14 Bean Uf
Código XML 2.2 Spring-beans.xml
Diego Pacheco – http://diego-pacheco.blogspot.com
2-16
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.singleton; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUfs { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/singleton/Springbeans.xml"); Uf bean1 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean1.getUfsBrazil()); bean1.showInstance(); Uf bean2 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean2.getUfsBrazil()); bean2.showInstance(); Uf bean3 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean3.getUfsBrazil()); bean3.showInstance(); } }
Código 2.15 Teste Se executarmos esse programa, o resultado será algo semelhante ao representado na figura abaixo. Inicio do processamento dos estados... ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff
Código 2.16 Resultado da Execução Perceba que a criação dos estados ocorre somente na primeira vez, mas nas outras vezes já está em memória, logo além, se não fizer duas vezes o mesmo processamento, existe um ganho de performance.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-17
Spring Framework – Framework para desenvolvimento de aplicações java
Também é possível desativar esse comportamento, ou seja, é possível configurar no spring para que o bean em questão não seja criado como um Singleton. Para isso, basta alterar o registro do bean no Spring, conforme no XML abaixo:
Código XML 2.3 Spring-beans.xml Neste mesmo capítulo serão explicados e exemplificados melhor os possíveis escopos de beans no Spring.
Lazy Initialization Outro recurso importante é o Lazy Initialization, com ele podemos fazer com que o Spring só carregue os beans que forem solicitados, ou seja, se temos 50 beans declarados no contexto do Spring e apenas 10 são utilizados, os outros 40 beans não vão ser instanciados, e assim evitamos um processamento desnecessário e ganhamos em desempenho.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-18
Spring Framework – Framework para desenvolvimento de aplicações java
Para fazer tal configuração é necessário configurar no XML de beans do Spring o atributo lazy-init="true". Veja o exemplo de como faz isso no XML abaixo:
Código XML 2.4 Spring-beans.xml um exemplo lazy initialization. É sempre válido configurar esse comportamento do framework. O Default do Spring é começar com lazy-init=”false”,
então sempre que possível altere essa
configuração para true. Podemos configurar no Spring que todos os beans de um determinado arquivo XML de configurações por default assumam o mesmo valor, podemos fazer isso através do atributo default-lazy-init esse atributo só pode ser setado no modo beans que é a raiz de configurações.
Código XML 2.4 Spring-beans.xml um exemplo de default lazy initialization.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-19
Spring Framework – Framework para desenvolvimento de aplicações java
Scopos dos Beans
Scopo se refere à visibilidade de um objeto gerenciado pelo Spring e também está relacionado ao seu tempo de vida. Existem os seguintes scopos de beans no Spring.
Scopo
Descrição
singleton
Uma única instância de objeto para todo o contexto do Spring.
prototype
Múltiplas instâncias de um objeto para o container do Spring.
request *
Escopo relacionado ao ciclo de vida HTTP Request, a cada request teremos outra instância de bean no Spring
session *
Escopo relacionado ao ciclo de vida HTTP Session, uma única instância do Bean por session.
global
Escopo relacionado ao ciclo de vida global HTTP Session, bean
session *
válido em uma session global. Utilizado para portlets.
* Escopos que só são válidos em um contexto web-aware, ou seja, em uma aplicação JSP/Servlet ou JEE. Criados por uma factory específica para Web, como por exemplo: XmlWebApplicationContext.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-20
Spring Framework – Framework para desenvolvimento de aplicações java
Podemos ver na prática a diferença entre singleton e prototype no exemplo abaixo. Nesse exemplo o mesmo bean é registrado de maneiras diferentes, isso é perfeitamente possível. package com.targettrust.spring.scope; public class SimpleBean { private Long id = 0L; public SimpleBean() {} public SimpleBean(Long id) { super(); this.id = id; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public String toString() { return super.toString() + " id: " + id; } }
Código 2.17 SimpleBean.java.
Código XML 2.5 Spring-beans.xml xml de configuração.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-21
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.scope; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestScope { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/scope/Springbeans.xml"); SimpleBean SimpleBean SimpleBean SimpleBean
beanA beanA1 beanB beanB1
= = = =
(SimpleBean)bf.getBean("beanA"); (SimpleBean)bf.getBean("beanA"); (SimpleBean)bf.getBean("beanB"); (SimpleBean)bf.getBean("beanB");
System.out.println("BeanA System.out.println("BeanA1 System.out.println("BeanB System.out.println("BeanB1
: : : :
" " " "
+ + + +
beanA); beanA1); beanB); beanB1);
} }
Código 2.18 Teste de Scopes.
Diego Pacheco – http://diego-pacheco.blogspot.com
2-22
Spring Framework – Framework para desenvolvimento de aplicações java
Criando seu próprio scope No Spring framework 2.0.X podemos criar nosso próprio scope e ainda mais, podemos redefinir os scopos baseados em web-aware. Os únicos scopos que são intocáveis são: prototype e singleton, se tentarmos reescrevê-los o Spring irá levantar uma IllegalArgumentException. Imagine que em sua aplicação surgiu a necessidade de ter controle sobre todos os objetos Pessoa criados, como poderíamos fazer isso sem reescrever toda a aplicação? Criando o nosso próprio scopo de bean seria uma forma. package com.targettrust.spring.scope.myscope; public class Pessoa { private String nome; public Pessoa() { } public Pessoa(String nome) { super(); this.nome = nome; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((nome == null) ? 0 : nome.hashCode()); return result; } @Override public boolean equals(Object obj) { return (obj == null) ? false : nome.equals(((Pessoa) obj).getNome()); } @Override public String toString() { return "nome: " + nome; } }
Código 2.19 Pessoa.java. Diego Pacheco – http://diego-pacheco.blogspot.com
2-23
Spring Framework – Framework para desenvolvimento de aplicações java
package com.targettrust.spring.scope.myscope; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; @SuppressWarnings("unused") public class TestScopes { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/scope/myscope/Spri ng-beans.xml"); Pessoa p1 = (Pessoa)bf.getBean("pessoa1"); Pessoa p2 = (Pessoa)bf.getBean("pessoa2"); Pessoa p3 = (Pessoa)bf.getBean("pessoa3"); Pessoa p4 = (Pessoa)bf.getBean("pessoa4"); System.out.println("Todas as pessoas: " + ThreadLocalScope.tl.get()); p3.setNome("Spider-Pig"); System.out.println("Todas as pessoas: " + ThreadLocalScope.tl.get()); } }
Código 2.20 Classe de testesTestScopes.java.
Código XML 2.6 Spring-beans.xml scope customizado. package com.targettrust.spring.scope.myscope; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope; public class ThreadLocalScope implements Scope{ public static ThreadLocal