Escolar Documentos
Profissional Documentos
Cultura Documentos
Spring Framework 2.0
Spring Framework 2.0
0)
Framework para
Desenvolvimento de Aplicaes
em Java
Diego Pacheco
Dez/2007
Sobre o Autor
Diego Pacheco
Tcnico em Processamento de Dados e graduando em Cincias da Computao(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 solues
corporativas em arquitetura JEE, provendo coaching/mentoring em software e processo
de desenvolvimento de software. Gosto muito de msica, tocar guitarra, jogar PSP,
Bloggar, Ler e principalmente as incrveis histrias do Conan. Mantenho o blog <
http://diego-pacheco.blogspot.com/> a mais de 3 anos.
Sumrio
1. Introduo .................................................................................................................... 1-1
Objetivos ...................................................................................................................................1-2
Conceitos Bsicos .................................................................................................................1-3
Cenrios de uso ....................................................................................................................1-7
Portiflio ...............................................................................................................................1-10
Download ..............................................................................................................................1-12
Estrutura de Diretrios ..................................................................................................1-13
Exerccios ..............................................................................................................................1-15
Espao para anotaes ....................................................................................................1-16
BeanFactoryPostProcessors ............................................................................................3-21
Property Editors .................................................................................................................3-25
Eventos ....................................................................................................................................3-30
PropertyPlaceholderConfigurer .................................................................................3-33
SingletonBeanFactoryLocator ......................................................................................3-36
Internacionalizao .........................................................................................................3-40
Exercicios ..............................................................................................................................3-44
Espao para anotaes ....................................................................................................3-45
II
III
1. Introduo
Objetivos
1-2
Conceitos Bsicos
1-3
melhor programar para interfaces do que para classes, Spring reduz o custo
e a complexidade de usar interfaces para zero.
1-4
1-5
1-6
Cenrios de uso
Podemos utilizar Spring nos mais diversos cenrios, desde um simples applet
at mesmo nas mais complexas aplicaes corporativas. Um exemplo tpico de uso
do Spring em uma aplicao completa Java EE onde teremos:
1-7
1-8
Podemos usar Spring tambm se for necessrio fazer integrao com EJB,
possvel utilizar os recursos da camada de acesso e abstrao de EJB.
1-9
Portiflio
1-10
1-11
Download
O
Spring
Framework
pode
ser
obtido
atravs
do
site:
http://www.springframework.org/download existe a possibilidade de baixar
somente o framework ou baixar o framework e suas dependncias. A Verso do
Spring que ser usada nessa apostila a 2.0.6 , mas muitos itens descritos aqui so
vlido tambm para a verso 1.2.x do framework.
O Spring framework necessita apenas uma verso do 1.5 JDK ou superior,
no necessrio criar variveis de ambiente para o Spring. O Spring usa um
conjunto de frameworks muito grande, ento recomendado fazer download da
verso full com dependncia que tem por volta de 60Mb.
1-12
Estrutura de Diretrios
aspectj: Fontes dos testes dos artefatos que utilizam aspectj, aqui temos
alguns artefatos de transao feitos em aspectJ.
dist: Distribuio binrias dos fontes do Spring, aqui voc encontrar os jars
do Spring, bem como todos os jars de todos os mdulos separados.
docs: Contem toda a documentao do Spring, nessa voc ir encontrar o
JavaDoc, Reference Guide, documentao das taglibs do Spring.
lib: Nesse diretrio esto todas as dependncias diretas e indiretas do Spring
framework, aqui voc encontrar jars de diversos frameworks, como por exemplo
hibernate, struts, junit, ant.
1-13
1-14
Exerccios
1-15
1-16
2. Container IoC
Objetivos
2-2
Desacoplamento
2-3
package com.targettrust.spring.bad;
import java.util.List;
public class Autor {
private String nome;
private List<Livro> 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<Livro> getLivros() {
return livros;
}
public void setLivros(List<Livro> livros) {
this.livros = livros;
}
}
2-4
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;
}
}
2-5
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<Livro> livros = new ArrayList<Livro>();
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 no","Variados Editora",2002));
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();
}
}
2-6
2-7
2-8
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
2-9
2-10
package com.targettrust.spring.bad.ok;
import java.util.ArrayList;
import java.util.List;
public class Listar implements Listavel{
public List<Publicavel> list(String nome) {
Autor a = new Autor("Diego Pacheco");
List<Publicavel> publicaveis = new ArrayList<Publicavel>();
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 no","Variados
Editora",2002));
List<Publicavel> achados = new ArrayList<Publicavel>();
for(Publicavel p: publicaveis){
if (p.getAutor().equals(nome))
achados.add(p);
}
return achados;
}
}
2-11
2-12
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 configuraes que podemos fazer
sobre esses beans, mas vamos comear mostrando como declarar um bean no
Spring.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>
<bean
id="autor"
class="com.targettrust.spring.bad.ok.Autor"
/>
</beans>
2-13
precisa
ser instanciada,
nesse
exemplo
foi
usado
factory
2-14
2-15
ufs.add(new
ufs.add(new
ufs.add(new
ufs.add(new
ufs.add(new
Uf("Rorima","RR"));
Uf("So 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<Uf> getUfsBrazil(){
return ufs;
}
public void showInstance(){
System.out.println(super.toString());
}
public String toString() {
return sigla;
}
}
2-16
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();
}
}
2-17
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 so utilizados, os outros 40 beans no
vo ser instanciados, e assim evitamos um processamento desnecessrio e ganhamos
em desempenho.
2-18
<bean
id="uf"
class="com.targettrust.spring.singleton.Uf"
scope="prototype"
lazy-init="true"
/>
</beans>
2-19
Scopo
Descrio
singleton
prototype
request *
session *
global
session *
2-20
2-21
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);
}
}
2-22
2-23
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());
}
}
2-24
scope="threadLocal"
>
<property name="nome" value="Rod Johnson"/>
</bean>
<bean id="pessoa3"
class="com.targettrust.spring.scope.myscope.Pessoa"
scope="threadLocal"
>
<property name="nome" value="Juergen Hoeller"/>
</bean>
<bean id="pessoa4"
class="com.targettrust.spring.scope.myscope.Pessoa"
scope="singleton"
>
<property name="nome" value="Ninguem me viu!!!"/>
</bean>
</beans>
2-25
return obj;
}
}
@Override
public void registerDestructionCallback(String name, Runnable
callback){
throw new UnsupportedOperationException("Essa operao de
registerDestructionCallback, no suportada!");
}
@Override
public String getConversationId() {
return null;
}
}
org.springframework.beans.factory.config.Scope,
implementao
2-26
Essa uma das duas formas que o Spring faz injeo de dependncias, ele
utiliza um mtodo setter conforme padro da Sun e atravs desse mtodo setta os
valores no objeto em questo.
package com.targettrust.spring.setter;
public class Aluno {
private
private
private
private
String nome;
Integer idade;
boolean desconto;
Character sexo;
public Aluno() {}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Integer getIdade() {
return idade;
}
public void setIdade(Integer idade) {
this.idade = idade;
}
public boolean isDesconto() {
return desconto;
}
public void setDesconto(boolean desconto) {
this.desconto = desconto;
}
public Character getSexo() {
return sexo;
}
public void setSexo(Character sexo) {
this.sexo = sexo;
}
@Override
public String toString() {
return "nome: " + nome +
" idade: " + idade +
" desconto: " + desconto +
" sexo: " + sexo;
}
}
2-27
No existe nada de mgico na injeo via setter, simples, basta ter o mtodo
setter e o tipo de dado injetado ser o mesmo.
2-28
2-29
Caso voc tenha um construtor que receba uma String e um nmero, o Spring
pode acabar sentando valores indesejados, para resolver esse tipo de situao,
podemos especificar o tipo do argumento do construtor, conforme exemplo de XML
abaixo.
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
2-30
value="Black" />
value="Dog" />
</bean>
Cdigo XML 2.11 Exemplo de tipo de argumento para construtor com index.
Injeo de colees
Por deafult o Spring possui tags especficas para injeo de colees, possvel
injetar: Map, List, Properties e Set. De fato podemos injetar qualquer Collection, mas
para injetar uma coleo que no seja uma das citadas, ser necessrio usar um
Custon Property Editor. Para fazer as injees das colees nativas do Spring,
utilizamos as tags: <map/>, <list/>, <set/> e <props/>. Considerando o seguinte
exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>
<bean
id="estadio"
class="com.targettrust.spring.collection.Estadio"
>
<property name="pessoas">
<set>
<value>Diego</value>
<value>Rod</value>
<value>Alef</value>
</set>
</property>
<property name="cadeiras">
<map>
<entry>
<key><value>1</value></key>
<value>diego</value>
</entry>
<entry>
<key><value>2</value></key>
<value>Rod</value>
2-31
</entry>
</map>
</property>
<property name="vededoresPipoca">
<list>
<value>Ze</value>
<value>JoZe</value>
<value>MaisEh</value>
</list>
</property>
<property name="detalhes">
<value>
estadio.luz=forte
estadio.taman.hq.full=grande
estadio.fundac.since=10/10/2001
estadio.status.now=ativo
</value>
</property>
</bean>
</beans>
java.util.List;
java.util.Map;
java.util.Properties;
java.util.Set;
Set<String> pessoas;
Map<Integer, String> cadeiras;
List<String> vededoresPipoca;
Properties detalhes;
public Estadio() {}
public Set<String> getPessoas() {
return pessoas;
}
public void setPessoas(Set<String> pessoas) {
this.pessoas = pessoas;
}
2-32
2-33
Dica: Se for explicitamente necessrio injetar uma coleo nula, ou settar null em
alguma propriedade de algum bean do Spring, podemos utilizar a tag <null/>.
2-34
2-35
2-36
2-37
2-38
2-39
possvel
utilizar
o
listener
org.springframework.web.context.ContextLoaderListener
ou
o
Servlet
org.springframework.web.context.ContextLoaderServlet.
Basta configurar isso no web.xml de sua aplicao, conforme exemplo abaixo:
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/Spring-beans.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- ou use o ContextLoaderServlet ou invs
de usar o listener
acima.
<servlet>
<servlet-name>context</servlet-name>
<servletclass>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
-->
</web-app>
2-40
Para testar, vamos empacotar essa aplicao em um arquivo war. Para fazer
esse teste vamos chamar o servio do Spring atravs de uma pgina jsp. Confira o
cdigo abaixo:
<%@page language="java" contentType="text/html; charset=ISO-8859-1"%>
<%@page
import="org.springframework.web.context.support.WebApplicationContextUtils
"%>
<%@page import="com.targettrust.spring.web.DateService"%>
<html>
<title>Spring WEB</title>
<body>
<center><h2>Exemplo de Spring com WEB-Tier</h2></center><br>
A Data atual :
<%=((DateService)WebApplicationContextUtils.getWebApplicationContext(getSe
rvletConfig().getServletContext()).getBean("dateService")).getDate()%>
</body>
</html>
2-41
Exerccios
2-42
2-43
3. Manipulao de Beans
Objetivos
3-2
Resource Loaders
3-3
Init-Metohd e InitializingBean
O Spring prove alguns mecanismos de call back aps a inicializao de um
bean. Aps o container de IoC do Spring resolver as injees de dependncias ele
prove um Call Back, ou seja, ele pode estar invocando um mtodo em sua classe e a
partir desse mtodo voc realiza algum processamento. Essa operao pode ser
configurada atravs da propriedade init-method. Essa soluo elegante, pois no
gera acoplamento entre o cdigo do Spring e seu cdigo. Veja isso na prtica no
exemplo abaixo:
package com.targettrust.spring.init;
import java.util.Date;
public class HoraCertaService {
private Date data;
private String pais;
public HoraCertaService() {
System.out.println("Criando Bean de HoraCertaService ");
}
public void preparar(){
data = new Date();
System.out.println("Ajustado a hora para o pais: " + pais);
}
@SuppressWarnings("deprecation")
public String getHoraCerta(){
return pais + " -> " + data.getHours() + ":" +
data.getMinutes() + ":" + data.getSeconds();
}
3-4
</beans>
Assim como existe a propriedade init-method existe a propriedade destroymethod que um Call Back para quando o container destrudo. possvel utilizar
uma
interface
para
esse
Call
Back,
a
interface
3-5
3-6
Herana de Definies
3-7
3-8
value="pacheco@diego.com.spring" />
<property name="telefone" value="455-55-55" />
</bean>
<bean
abstract="false"
id="pessoaFisicaService"
class="com.targettrust.spring.extend.PessoaFisicaService"
parent="pessoaService"
>
<property name="cpf" value="47888971210" />
</bean>
</beans>
3-9
Validao
3-10
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Integer getIdade() {
return idade;
}
public void setIdade(Integer idade) {
this.idade = idade;
}
}
3-11
3-12
Bean Wrapper
Bean Wrapper um recurso do Spring que funciona com Java beans como o
prprio nome j diz, Java beans um especificao da Sun que define se um
determinado objeto deve ter um construtor vazio e mtodos getters e setters de
acordo com o padro da Sun camelCase. Essa funcionalidade na verdade um
pattern do GOF que se chama decorator. Que tambem conhecido como Wrapper
que significa empacotar, no caso ns temos uma camada de adiciona um
funcionalidade adicional a algo existente.
Esse recurso pode ser utilizado para fazer manipulaes com propriedades
de objetos de maneira elegante. Tambm usual para fazer algum tipo de bind em
sua aplicao. Confira como codificar abaixo:
package com.targettrust.spring.beanwrapper;
public class Funcionario {
private String nome;
private Long salario;
public Funcionario() {}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Long getSalario() {
return salario;
}
public void setSalario(Long salario) {
this.salario = salario;
}
@Override
public String toString() {
return "Funcionario[ nome: " + nome +
" , salario: " + salario + " ]";
3-13
}
}
3-14
</bean>
</beans>
3-15
Expresso
Descrio
nome
conta.valor
filhos[2]
estado[poa]
3-16
BeanPostProcessors
3-17
Esse tipo de Registro no conveniente, por causa disso que para muitas
aplicaes as pessoas preferem utilizar ApplicationContex ao invs de BeanFactory.
Classes que implementam BeanPostProcessor so classes especiais, logo so
tratadas de maneira diferente pelo container. Todas as BenPostProcessors e aqueles
beans que estejam diretamente referenciados por eles sero instanciados ao startup
do Spring.
Os recursos de AOP auto-proxing so implementados como
BeanPostProcessor,
nenhum BeanPostProcessor
ou
beans diretamente
referenciados sero elegveis para auto-proxy, ou seja, no haver aspectos sobre
eles. O Spring ir lhe alertar sobre essa situao com uma mensagem semelhante a
essa: Bean 'foo' is not eligible for getting processed by all BeanPostProcessors (for
example: not eligible for auto-proxying). Veja um exemplo prtico de como utilizar
este recurso:
package com.targettrust.spring.beanpostprocessors;
public class ObjetoA {
}
3-18
package com.targettrust.spring.beanpostprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class LogCreationBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String
beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String
beanName)
throws BeansException {
System.out.println("Craindo bean: " + beanName);
return bean;
}
}
3-19
package com.targettrust.spring.beanpostprocessors;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class Teste {
public static void main(String[] args) {
new
ClassPathXmlApplicationContext("/com/targettrust/spring/beanpostprocessor
s/Spring-beans.xml");
}
}
3-20
BeanFactoryPostProcessors
Similar ao BeanPostProcessor, porm o BeanFactoryPostProcessor consegue
ler os metadados de configurao do Spring e tambm mudar esses dados antes
que
o
Spring
crie
seus
beans.
Voc
pode
configurar
muitos
BenFactoryPostProcessor. possvel configurar a ordem de execuo dessa classe
implementando a interface Ordered. Se voc deseja mudar a instncia de um bean
j criado voc deve utilizar o BeanPostProcessor conforme apresentando no tpico
anterior.
O
Prprio
Spring
utiliza
beanFactoryPostProcessor
como:
PropertyResourceConfigurer e PropertyPlaceholderConfigurer.
Se estamos utilizando ApplicationContext o registro feito de forma
automtica, se estivermos utilizando uma BeanFactory precisamos fazer isso de
forma manual. A Forma de fazer isso est exemplificada logo abaixo:
XmlBeanFactory factory = new XmlBeanFactory(new
FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);
3-21
}
}
java.io.FileInputStream;
java.util.Map;
java.util.Properties;
java.util.Map.Entry;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class DatePatternRouterBeanFactoryPostProcessor implements
BeanFactoryPostProcessor {
@Override
@SuppressWarnings("unchecked")
public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
Properties p = new Properties();
try {
p.load(new
FileInputStream("./src/com/targettrust/spring/beanfactorypostprocessors/p
atterns.properties"));
System.out.println("Patterns: " + p);
} catch (Exception e) {
throw new FatalBeanException("Erro ao buscar
patterns!",e);
}
Map<Object,Object> beans =
beanFactory.getBeansOfType(DataService.class);
for(Entry<Object, Object> e: beans.entrySet()){
System.out.println("Aplicando pattern em service: " +
e);
DataService service = ((DataService)e.getValue());
service.setPattern(p.getProperty("pattern." +
service.getPattern().replace("#", "")));
}
}
}
3-22
3-23
3-24
Property Editors
Explicao
Editor para arrays de bytes. Strings vo ser convertidas
em suas correspondentes representaes de bytes.
ClassEditor
CustomBooleanEditor
3-25
CustomCollectionEditor
CustomDateEditor
CustomNumberEditor
FileEditor
InputStreamEditor
LocaleEditor
PatternEditor
PropertiesEditor
StringTrimmerEditor
URLEditor
3-26
Voc pode criar seu prprio Property Editor, para isso voc precisar
estender a classe PropertyEditorSupport e registrar esse custom editor criado por
voc no XML do Spring. Veja o exemplo a seguir:
package com.targettrust.spring.propertyeditor;
public class Aluno {
private String nome;
public Aluno() {}
public Aluno(String nome) {
super();
this.nome = nome;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public String toString() {
return nome;
}
}
3-27
package com.targettrust.spring.propertyeditor;
import java.util.List;
public class Turma {
private String nome;
private List<Aluno> alunos;
public Turma() {}
public Turma(String nome, List<Aluno> alunos) {
super();
this.nome = nome;
this.alunos = alunos;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<Aluno> getAlunos() {
return alunos;
}
public void setAlunos(List<Aluno> alunos) {
this.alunos = alunos;
}
@Override
public String toString() {
return nome + " alunos: " + alunos.toString();
}
}
3-28
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="turma"
class="com.targettrust.spring.propertyeditor.Turma">
<property name="nome" value="Curso-Spring" />
<property name="alunos">
<list>
<value>Rod</value>
<value>Joe</value>
<value>Bart</value>
<value>Homer</value>
<value>Hammer</value>
</list>
</property>
</bean>
<bean id="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigu
rer">
<property name="customEditors">
<map>
<entry
key="com.targettrust.spring.propertyeditor.Aluno">
<bean
class="com.targettrust.spring.propertyeditor.AlunoEditor" />
</entry>
</map>
</property>
</bean>
</beans>
3-29
Eventos
A escuta de eventos em um objeto ApplicationContext feita atravs dos
objetos ApplicationEvent e ApplicationListener. Se um bean implementa a interface
ApplicationListener publicado no contexto do Spring toda vez que for publicado
um evento do tipo ApplicationEvent o seu bean vai ser notificado. Confira alguns
dos eventos disponveis por padro na ApplicationContext.
Evento
Descrio
ContextRefreshedEvent
ContextClosedEvent
RequestHandleEvent
3-30
3-31
id="funcionarioEsperto"
class="com.targettrust.spring.event.FeriadoListener"
/>
</beans>
Nesse exemplo foi utilizado o FeridoEvent que uma classe que estende
ApplicationEvent do Spring. Para tratar o evento foi criada a classe FeriadoListener
que implementa ApplicationListener com um if parta saber se o evento disparado foi
o FeriadoEvent. A Classe RH uma ApplicationContextAware para poder publicar o
evento atravs do mtodo publishEvent.
3-32
PropertyPlaceholderConfigurer
String nome;
int idade;
String time;
float altura;
public Instrutor() {}
public Instrutor(String nome, int idade, String time, float altura)
{
super();
this.nome = nome;
this.idade = idade;
this.time = time;
this.altura = altura;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getIdade() {
return idade;
3-33
}
public void setIdade(int idade) {
this.idade = idade;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public float getAltura() {
return altura;
}
public void setAltura(float altura) {
this.altura = altura;
}
@Override
public String toString() {
return " nome: " + nome +
" idade: " + idade +
" altura : " + altura+
" time: " + time ;
}
}
3-34
class="com.targettrust.spring.propertyplaceholderconfigurer.Instrut
or"
>
<property
<property
<property
<property
</bean>
name="nome"
name="idade"
name="time"
name="altura"
value="${nome}" />
value="${idade}" />
value="${time}" />
value="${altura}" />
</beans>
nomeBean.propriedade=valor
outronomeBean.outrapropriedade=outrovalor
maisumnomeBean.maisumapropriedade=maisumvalor
3-35
SingletonBeanFactoryLocator
3-36
default-lazy-init="true"
>
<bean
id="A2"
class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA"
/>
</beans>
3-37
<constructor-arg>
<list>
<value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-A.xml</value>
<value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-B.xml</value>
<value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-C.xml</value>
</list>
</constructor-arg>
</bean>
<bean
id="beanFactoryBean2"
class="org.springframework.context.support.ClassPathXmlApplicationC
ontext"
>
<constructor-arg>
<list>
<value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-D.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
a1:
a2:
a3:
a4:
"
"
"
"
+
+
+
+
a1);
a2);
a3);
a4);
3-38
}
}
3-39
Internacionalizao
para
adicionar
3-40
package com.targettrust.spring.i18n;
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
public class Pessoa implements MessageSourceAware{
private String nome;
private int idade;
private MessageSource ms;
public Pessoa() {}
public Pessoa(String nome, int idade) {
super();
this.nome = nome;
this.idade = idade;
}
@Override
public void setMessageSource(MessageSource messageSource) {
ms = messageSource;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
if( idade<=0 || idade >= 120 )
throw new
IllegalArgumentException(ms.getMessage("idade.invalida",new
Object[]{idade},Locale.getDefault()));
this.idade = idade;
}
@Override
public String toString() {
return "nome: " + nome + " idade: " + idade;
}
}
3-41
3-42
}
private static void setIdade(ApplicationContext ac){
Pessoa p = (Pessoa)ac.getBean("pessoa");
p.setNome("Crom");
try{
p.setIdade(200);
}catch(RuntimeException re){
re.printStackTrace();
}
}
}
3-43
Exercicios
3-44
3-45
4. Persistncia
Objetivos
4-2
Hierarquia de Exceptions
O Spring framework prov uma camada de acesso a dados chamada DAO support
que prove diversas facilidades para trabalhar com JDBC, Hibernate, JDO, JPA. Esse recurso
permite trocar a tecnologia de persistncia com mais facilidade e menos esforo, sem a
necessidade de se preocupar com as execptions que variam de tecnologia para tecnologia.
O Spring tem sua prpria rvore de exceptions traduzindo as exceptions de tecnologias
especficas como SQLException para sua prpria rvore de exceptions, onde sua exception
raiz a DataAccessException. Esses exceptions empacotam a exception raiz, assim voc
no perde nenhuma mensagem original.
O Spring pode encapsular uma exception do Hibernate, por exemplo, em uma outra
exception de sua rvore, isso igual para as exceptions do JDO e da JPA tambm. Este
mecanismo do Spring lhe evita a irritao de ter que tratar exceptions que voc no pode
se recuperar.
Confira a rvore de exceptions do Spring na figura abaixo:
4-3
Super
classe
de
accesso
via
JDO,
necessita
uma
JDO,
necessita
uma
Super
classe
de
accesso
via
4-4
4-5
No Spring possvel configurar sua fonte de dados de forma que seja possvel obter
o DataSource de uma fonte JNDI. Podemos utilizar um DriverManagerDataSource que
uma simples implementao de DataSource que devemos informar o driver a ser utilizado,
conforme exemplo abaixo:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>
<bean
id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
lazy-init="false"
>
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://C:/db" />
<property name="username" value="sa" />
<property name="password" value=""
/>
</bean>
</beans>
Para criarmos esse objeto necessrio informar o driver, a url de conexo para o
banco, usurio e a senha. Nesse caso est sendo utilizado uma conexo com o banco de
dados HSQLDB. Esse DataSource no disponibiliza pools de conexes, a cada chamada ser
criada uma conexo nova.
Se voc deseja uma soluo de connection pool out-of-the-box, deve considerar a
soluo da apache o Apache DBCP, possvel utilizar esses framework em conjunto com o
Spring.
Dica: O Spring framework faz a traduo de erros de SQL Genricos para Exceptions mais
especficas, se voc desenvolve alguma regra ou processamento em stored procedures ou
functions de bancos e lavanta exceptions personalizadas no banco, podemos traduzir essas
exceptions personalizadas para exceptions do Java.
Para fazer isso necessrio herdar a classe SQLErrorCodeSQLExceptionTranslator e
implementar o mtodo custom translate onde voc ir traduzir as exceptions.
4-6
A Classe JdbcTemplate tem uma srie de mtodos utilitrios, dentre eles podemos
destacar:
Execute (String sql): utilizado para executar comandos ddl.
Update (String sql,Object[] args): utilizado para executar inserts e updates esse
mtodo recebe um Object[] por que ele cria um PreparedStatement. Esse mtodo
pode ser utilizado para efetuar operaes de delete tambm.
4-7
4-8
package com.targettrust.spring.jdbc;
import
import
import
import
import
org.springframework.context.ApplicationContext;
org.springframework.context.support.ClassPathXmlApplicationContext;
org.springframework.jdbc.UncategorizedSQLException;
org.springframework.jdbc.core.JdbcTemplate;
org.springframework.jdbc.core.RowMapper;
4-9
4-10
O Spring prove suporte para gerenciar uma SessionFactory do Hibernate. Essa tarefa
pode ser feita atravs do LocalSessionFactoryBean. Esse bean necessita de uma DataSource
e de recursos de mapeamentos podendo ser um hibernate mappings ou configuraes de
mapeamento feitas no prprio Spring que seram repassadas ao Hibernate. muito comum
utilizar esse tipo de recurso em uma aplicao JEE ou desktop.
O Seguinte exemplo mostra como configurar uma SessionFactoryBean de forma
que o Spring gerencia a SessionFactory do Hibernate com o Banco de dados HSQLDB.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>
<bean
id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
lazy-init="false"
>
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url"
value="jdbc:hsqldb:file:///C:\\target\\spring\\db" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
lazy-init="false"
>
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>com/targettrust/spring/hibernate/Pessoa.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PointbaseDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
</beans>
4-11
package com.targettrust.spring.hibernate;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TesteSessionFactory {
public static void main(String[] args) {
ApplicationContext ac =
new
ClassPathXmlApplicationContext("/com/targettrust/spring/hibernate/Springbeans.xml");
SessionFactory sf = (SessionFactory)ac.getBean("sessionFactory");
System.out.println(sf.openSession());
}
}
Nesse exemplo foi necessrio utilizar o hsqldb.jar, pois nesse jar que esto os drivers de
acesso ao banco de dados hsqldb, se voc quiser utilizar outro banco de dados em sua
aplicao, voc dever trocar esse jar pelo jar apropriado para seu banco de dados.
4-12
Hibernate Template
find (String hql): Esse mtodo faz uma busca atravs de um HQL e retorna
uma List.
Delete (String hql): Mtodo que deleta dados no banco a partir de uma query
hsql.
Voc pode utilizar os call backs disponibilizados pelo Spring se quiser ter acesso
prpria SessionFactory do Hibernate, porm, com as facilidades do Spring de abrir/fechar a
Session Factory, isso pode ser feito no mtodo execute que recebe um HibernateCallBack
que uma interface do Spring.
Veja no exemplo abaixo a utilizao desses mtodos citados acima:
4-13
package com.targettrust.spring.hibernate;
public class Pessoa {
private Long id;
private String nome;
private String email;
public Pessoa() {}
public Pessoa(String nome, String email) {
super();
this.nome = nome;
this.email = email;
}
public Pessoa(Long id, String nome, String email) {
super();
this.id = id;
this.nome = nome;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "nome: " + nome + ", email: " + email;
}
}
4-14
4-15
lazy-init="false"
>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
org.hibernate.criterion.DetachedCriteria;
org.springframework.context.ApplicationContext;
org.springframework.context.support.ClassPathXmlApplicationContext;
org.springframework.dao.DataAccessException;
org.springframework.orm.hibernate3.HibernateTemplate;
4-16
4-17
Transaes Declarativas
Para ter esse tipo de recurso necessrio ter um servidor de aplicao como, por
exemplo, JBOSS ou ORACLE IAS, mas se estou em uma aplicao java que roda fora de
uma servidor JEE? Estou fadado a trabalhar com o gerenciamento de transaes em baixo
nvel programaticamente? Se voc usa Spring framework a resposta no! O Spring
capaz de fazer isso por ns e ainda mais, com Spring possvel ter transaes declarativas
com aplicaes JDBC.
De forma programtica podemos ter controle transacional atravs do
TransactionTemplate do Spring que pode ser utilizado com o Hibernate.
HibernateTransactionManager o TransactionManager do Spring para hibernate 3, esse
objeto necessita de uma SessionFactory. Com o transactionTemplate podemos executar
um
cdigo
atravs
do
mtodo
execute
que
pode
receber
um
TransactionCallBackWithoutResult para realizarmos alguma operao no banco. Apesar de
o Spring facilitar esse trabalho, ainda assim essa abordagem custosa e pouco produtiva.
A alternativa para esse problema pode ser o suporte de transaes declarativas do
Spring framework. Esse mecanismo substitui as chamadas programticas por interceptor
AOP aliados a proxys para adicionar o controle transacional.
Dessa forma o componente pode se focar nas regras de negcio e o controle
transacional ficar isolado de forma que poderemos trocar essa implementao sem afetar
as regras de negcio da aplicao.
Com o mecanismo de transaes declarativas do Spring possvel utilizar um
contexto de transao gerenciado pelo HibernateTransactionManager com uma nica
SessionFactory em uma ThreadLocal e depois trocar para transaes distribudas com JPA
apenas trocando o manager de transao, sem afetar nada no seu cdigo j escrito.
Antes do Spring 2.0 nos Springs 1.X.X era utilizado o TransactionProxyFactoryBean,
ainda possvel utilizar esse recurso, o Spring prove total compatibilidade com isso.
Existe uma grande vantagem em utilizar o HibernateTransactionManager por que
ele ir expor a transao a nvel de conexo JDBC por DataSource, ou seja, se criarmos um
JdbcTemplate com o mesmo DataSource da SessionFactory do Transactionanager teremos
controle transacional entre Hibernate e JDBC de forma declarativa.
4-18
DataSource
SessionFactoryBean
HibernateTransactionManager
AOP Config
TxAdvice
4-19
Agora a configurao AOP para indicar como as classes devem ser interceptadas
pela transao declarativa e quando interceptadas que advice elas devem utilizar. Aqui
informamos que queremos interceptar todos os mtodos da classe ProdutoService, no
importando o mtodo e os parmetros passados. Nessa configurao foi informado para
utilizar um Advice.
<!-- Definio da configurao AOP, aqui criado um pointcut que define os
pontos do sistema
que sero interceptados, nesse caso a execuo de quaisquer mtodos
do ProdutoService.
Depois ele vincula essas classes interceptadas com um advice o
txAdvice;
-->
<aop:config>
<aop:pointcut id="produtoServiceMtodos" expression="execution(*
com.targettrust.spring.transaction.ProdutoService.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="produtoServiceMetodos"
/>
</aop:config>
No Advice estamos definindo que mtodos devem ter escopo transacional de fato.
Os mtodos definidos so: findAll que necessitar de uma transao ativa, se essa
transao no estiver ativa ele ir criar uma nova, esse mtodo est marcado como
somente leitura, ou seja, ele s faz consultas na base. O outro mtodo o salvar* , significa
que todos os mtodos que comecem com salvar sero transacionados e tero
comportamento igual ao findAll, porm esses mtodos salvar podem fazer modificaes
na base de dados.
<!-- Definio do Advide AOP que casa o gerente de transaes com os mtodos
Esse beans informa que mtodos e como esses mtodos devem
ser tratados pela transao -->
<tx:advice id="txAdvice" transaction-manager="txManager">
4-20
<tx:attributes>
<tx:method name="salvar*" propagation="REQUIRED" />
name="findAll"
propagation="REQUIRED" read-only="true"/>
</tx:attributes></tx:advice>
<tx:method
4-21
Exerccios
4-22
4-23
5. Facilitadores
Objetivos
5-2
Envio de E-mails
5-3
/>
5-4
Nesse bean definimos uma mensagem de e-mail especifica, nesse caso um email apenas de testes, esse bem construdo a partir de um template que um
outro SimpleMailMessage isso feito via injeo de construtor, nesse bean
configuramos para onde vai o e-mail e configuramos tambm o texto de
mensagem, colocar esse tipo de configurao no Spring interessante pois fica fcil
de manter e podemos reaproveitar para vrios trechos do sistema que necessite
enviar esse e-mail.
<bean
id="simpleMailMessage"
class="org.springframework.mail.SimpleMailMessage"
>
<constructor-arg index="0" ref="templateMessage"
/>
<property name="to"
value="dmetallica@gmail.com" />
<property name="text" value=" 123 Testando... "
/>
</bean>
Agora vem o programa Java, que faz o envio do e-mail de fato. requisitado
no contexto do Spring um SimpleMailMessage que a mensagem e um MailSender
para o envio.
package com.targettrust.spring.email;
import
import
import
import
import
org.springframework.context.ApplicationContext;
org.springframework.context.support.ClassPathXmlApplicationContext;
org.springframework.mail.MailException;
org.springframework.mail.MailSender;
org.springframework.mail.SimpleMailMessage;
5-5
org.springframework.context.ApplicationContext;
org.springframework.context.support.ClassPathXmlApplicationContext;
org.springframework.mail.MailException;
org.springframework.mail.javamail.JavaMailSender;
org.springframework.mail.javamail.MimeMessagePreparator;
5-6
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
public class TesteMimeMessageHelper {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"/com/targettrust/spring/email/Spring-beans.xml");
JavaMailSender ms = (JavaMailSender)ac.getBean("mailSender");
try{
MimeMessage message = ms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setFrom("form@server.com.br");
helper.setTo("dest@server.com");
helper.setText("Email MimeMessageHelper");
ms.send(message);
}catch(Exception e){
e.printStackTrace();
}
}
}
try{
MimeMessage message = ms.createMimeMessage();
5-7
try{
MimeMessage message = ms.createMimeMessage();
MimeMessageHelper helper = new
MimeMessageHelper(message,true);
helper.setFrom("form@server.com.br");
helper.setTo("dest@server.com");
helper.setText("<html><body><img
src='cid:img1'><br>Email MimeMessageHelper com suporte a imagems em
linha!</body></html>",true);
5-8
Importante: Para que a adio de recursos em linha funcione, voc deve adicionar
primeiro o text e depois o recurso respeitando o cid. Se no, pode ser que no
funcione corretamente.
5-9
5-10
Voc pode ver que atravs da propriedade timerTask ligamos o nosso service
de HoraCerta com esse agendamento de tarefa.
Agora s falta injetarmos essa configurao em uma factory de
agendamento de tempo.
<bean
id="timerFactory"
class="org.springframework.scheduling.timer.TimerFactoryBean"
>
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask" />
</list>
</property>
</bean>
5-11
5-12
5-13
Perceba que o nome da classe foi alterado para enfatizar que esse um
outro artefato e seu cdigo foi modificado de fato. Agora veja como ficam as
injees do Spring:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>
<bean
id="horaCertaServiceNaoAcoplada"
class="com.targettrust.spring.jdktask.HoraCertaServiceNaoAcoplada"
/>
<bean
id="scheduledTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask"
lazy-init="false"
>
<!-- Espera 0 ms antes de iniciar -->
<property name="delay" value="0" />
<!-- roda de 1 em 1 segundo -->
<property name="period" value="1000" />
<!-- Ir executar a TimerTask horaCertaService -->
<property name="timerTask" ref="executor" />
</bean>
<bean
id="executor"
class="org.springframework.scheduling.timer.MethodInvokingTimerTask
FactoryBean"
>
<property name="targetObject" ref="horaCertaServiceNaoAcoplada" />
<property name="targetMethod" value="showTime" />
</bean>
<bean
id="timerFactory"
class="org.springframework.scheduling.timer.TimerFactoryBean"
>
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask" />
</list>
</property>
</bean>
</beans>
5-14
O Que foi feito? Foi definido um bean chamado executor e esse bean um
MethodInvokingTimerTaskFactoryBean, onde a propriedade targetObject define
qual objeto ser invocado e a propriedade targetMethod define qual mtodo ser
chamado.
Depois esse bean
timerTask=executor.
associado
ao
scheduledTask
pela
propriedade
5-15
@Aspect Support
5-16
Vamos criar uma interface Service, que define o que os Services devem fazer.
package com.targettrust.spring.aop;
public interface Service {
public void fazAlgo();
}
5-17
Agora vamos registrar os beans no Spring, esse registro normal, bean id, classe
e o proxy aop.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
>
5-18
<aop:aspectj-autoproxy/>
<bean
id="aspecto"
class="com.targettrust.spring.aop.Aspecto"
lazy-init="false"
/>
<bean
id="sa"
class="com.targettrust.spring.aop.ServiceA"
/>
<bean
id="sb"
class="com.targettrust.spring.aop.ServiceB"
/>
<bean
id="sc"
class="com.targettrust.spring.aop.ServiceC"
/>
<bean
id="services"
class="java.util.ArrayList"
>
<constructor-arg index="0">
<list>
<ref bean="sa" />
<ref bean="sb" />
<ref bean="sc" />
</list>
</constructor-arg>
</bean>
</beans>
org.apache.commons.logging.Log;
org.apache.commons.logging.LogFactory;
org.aspectj.lang.ProceedingJoinPoint;
org.aspectj.lang.annotation.After;
org.aspectj.lang.annotation.Around;
org.aspectj.lang.annotation.Aspect;
org.aspectj.lang.annotation.Before;
@Aspect
public class Aspecto {
private static final Log log = LogFactory.getLog(Aspecto.class);
5-19
@Before("execution(* com.targettrust.spring.aop.Service.*(..))")
public void execucaoDeFazAlgoAntes() {
log.info("To sabendo antes da execuo de Service");
}
@After("execution(* com.targettrust.spring.aop.Service.*(..))")
public void execucaoDeFazAlgoDepois() {
log.info("To sabendo depois da execuo de Serice");
}
@Around("execution(*
com.targettrust.spring.aop.ServiceB.faz*(..)))")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws
Throwable {
Object retVal = pjp.proceed();
log.info("To sabendo around SericeB");
return retVal;
}
}
5-20
5-21
5-22
Testing Support
O Spring framework prove integrao com frameworks de teste unitrio
como por Junit e o TestNG. Dentre os recursos mais importantes podemos destacar
auto-wire automtica para propriedades protected e rollback no final da execuo.
Esse ltimo recurso importantssimo, pois podemos rodar um test e no final ele
sempre dar rollback, assim no iremos sujar a base de dados.
O Spring framerwork permite o uso de frameworks de mock objects como,
por exemplo, o easy mock. Isso muito til, pois dessa forma podemos testar
apenas a camada de services sem persistir na camada DAO, sendo que a camada
DAO pode ser composta de mocks. Assim isolando o teste dos Services e deixando
o teste rpido e funcional.
possvel rodar testes integrados sem a necessidade de se fazer deploy no
servidor de aplicao. Assim podemos testar recursos de SQL, Hibernate e transao
sem o servidor de aplicao, isso d melhor desempenho aos testes.
O mecanismo de test do Spring prove gerenciamento do contexto e cache,
para promover a performance.
5-23
AbstractDependencyInjectionSpringContextTests
Essa classe do Spring prove as facilidades de gerenciamento de contexto do
Spring, assim o primeiro mtodo de test a ser executado ser mais lento, porm os
outros vo ser muito mais rpidos pois utilizaram o contexto que j foi iniciado.
Para utilizar esse recurso necessrio implementar o mtodo:
protected String[] getConfigLocations() que deve retornar um array de String
com os arquivos de configuraes do Spring.
O Spring utiliza seus recursos de autoWire by type para dar produtividade
aos testes. Basta declarar um objeto e prover um setter que o Spring ir injetar
automaticamente esse objeto para voc.
package com.targettrust.spring.testing;
import java.util.Date;
public class DataService {
public Date getSysDate(){
return new Date();
}
}
5-24
5-25
de
testes
executar
2
O nome da varivel deve ser o mesmo nome do id do bean no Spring. E deve
ser protected.
Veja o cdigo de exemplo seguinte. Esse cdigo utiliza o mesmo service e o
mesmo arquivo xml do exemplo anterior.
package com.targettrust.spring.testing;
import java.util.Date;
import junit.framework.Assert;
import
org.springframework.test.AbstractDependencyInjectionSpringContextTests;
public class TestDataServiceWithProtected extends
AbstractDependencyInjectionSpringContextTests {
protected DataService dataService;
public TestDataServiceWithProtected() {
super.setPopulateProtectedVariables(true);
}
@Override
protected String[] getConfigLocations() {
return new
String[]{"classpath:com/targettrust/spring/testing/Spring-beans.xml"};
}
@SuppressWarnings("deprecation")
public void testDataDoDataService(){
Date d = dataService.getSysDate();
Date l = new Date();
Assert.assertEquals(d.getDay(),l.getDay());
Assert.assertEquals(d.getMonth(),l.getMonth());
Assert.assertEquals(d.getYear(),l.getYear());
}
}
5-26
AbstractAnnotationAwareTransactionalTests
5-27
AbstractTransactionalDataSourceSpringContextTests
Essa classe de testes utilizada para adicionar o suporte a transaes, e no
final do teste ir fazer roll back automaticamente. Se existir a necessidade de
efetuar o commit por causa de seu banco de dados, voc pode executar o mtodo
super.setComplete() no construtor, isso far com que o commit seja executado ao
invs do rollback.
Veja como utilizar esse recurso na prtica com esse teste abaixo:
package com.targettrust.spring.testing;
import org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.test.AbstractTransactionalDataSourceSpringContextTest
s;
import com.targettrust.spring.transaction.Produto;
import com.targettrust.spring.transaction.ProdutoService;
public class TesteTransactionWithRollBack extends
AbstractTransactionalDataSourceSpringContextTests {
protected ProdutoService produtoService;
protected JdbcTemplate jdbcTemplate;
public TesteTransactionWithRollBack() {
//super.setComplete();
super.setDefaultRollback(true);
super.setPopulateProtectedVariables(true);
}
@Override
protected String[] getConfigLocations() {
return new
String[]{"classpath:/com/targettrust/spring/transaction/Springbeans.xml"};
}
public void testSavePessoa() throws Exception{
Produto p = new Produto();
p.setNome("PRODUTO QUE NO DEVE APARECER NO BANCO DE DADOS");
p.setTipo("FANTASMA");
p.setValor(666d);
produtoService.salvar(p);
System.out.println(produtoService.findAll());
}
}
5-28
5-29
Agora vamos fazer uma implementao de servio padro para essa interface.
package com.targettrust.spring.remoting;
import java.util.Calendar;
import java.util.Date;
public class HoraServiceImpl implements HoraService{
public Date getDate() {
return Calendar.getInstance().getTime();
}
}
5-30
5-31
</beans>
5-32
5-33
Exerccios
5-34
5-35