Spring Capitulo 03
-
Upload
diego-pacheco -
Category
Documents
-
view
6.036 -
download
0
description
Transcript of Spring Capitulo 03
Conhecer os resource loaders do Spring
Saber utilizar o init-methodSaber utilizar a herança de
definições de beansSaber fazer classes de validaçõesConhecer o BeanWrapperConhecer os PostProcessors
Conhecer os principais properties editors
Conhecer os eventos do container
Saber utilizar o PropertyPlaceHolderConfigurer
Saber utilizar o SingletonBeanFactoryLocator
Conhecer os recursos de i18n
ResourcePatternResolver(ant style) file: classpath: wild-cards /* ServletContextResourceLoader Extensível, criar seu próprio
init-method• Executa método ao iniciar• init-method=“voidMethod”• Método público e void
Callbacks do Spring:• InitializingBean
• afterPropertiesSet
• DisposableBean• destroy
Dois colaboradores ou maisPropriedades abstract e parentEstrutura de HerançaReaproveitamento de injeções
package com.targettrust.spring.extend;public abstract class PessoaService {
private String nome;private String telefone;private String email;
public PessoaService() {}public String getNome() {
return nome;}public void setNome(String nome) {
this.nome = nome;}public String getTelefone() {
return telefone;}public void setTelefone(String telefone) {
this.telefone = telefone;}public String getEmail() {
return email;}public void setEmail(String email) {
this.email = email;}
}
package com.targettrust.spring.extend;public class PessoaFisicaService extends PessoaService {
private String cpf;
public PessoaFisicaService() {}public boolean validaCpf(){
return CpfUtils.validaCPF(cpf);}
public void mostraPessoa(){ if (validaCpf()){ System.out.println("nome: " + getNome() + " telefone: " + getTelefone() +
" email: " + getEmail() + " cpf: " + cpf);
}else{ System.out.println("Essa pessoa não tem um CPF Valido."); }}
public String getCpf() {return cpf;
}public void setCpf(String cpf) {
this.cpf = cpf;}
}
package com.targettrust.spring.extend;public class PessoaFisicaService extends PessoaService {
private String cpf;
public PessoaFisicaService() {}public boolean validaCpf(){
return CpfUtils.validaCPF(cpf);}
public void mostraPessoa(){ if (validaCpf()){ System.out.println("nome: " + getNome() + " telefone: " + getTelefone() +
" email: " + getEmail() + " cpf: " + cpf);
}else{ System.out.println("Essa pessoa não tem um CPF Valido."); }}
public String getCpf() {return cpf;
}public void setCpf(String cpf) {
this.cpf = cpf;}
}
<?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="pessoaService" class="com.targettrust.spring.extend.PessoaService" abstract="true" > <property name="nome" value="Diego" /> <property name="email" value="[email protected]" /> <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>
• Interface Validor• boolean supports (Class clazz);•void validate (Object target, Errors errors);
• VadationUtils•rejectIfEmpty•rejectValue•Retorno de erro via objeto (Spring MVC, tags de tela)
package com.targettrust.spring.validate;import org.springframework.validation.Errors;import org.springframework.validation.ValidationUtils;import org.springframework.validation.Validator;public class Pessoa implements Validator{
private String nome;private Integer idade;
public boolean supports(Class clazz) {return Pessoa.class.equals(clazz);
}public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "nome", "nome.vazio"); Pessoa p = (Pessoa) target;
if (p.getIdade() < 0) { errors.rejectValue("idade", "valor negativo"); } else if (p.getIdade() > 120) { errors.rejectValue("idade", "velho de mais"); }}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;}
}
<?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" default-lazy-init="true">
<bean id="pessoa" class="com.targettrust.spring.validate.Pessoa" > <property name="nome" value="Fulano" /> <property name="idade" value="-1" /> </bean>
</beans>
package com.targettrust.spring.validate;import org.springframework.beans.factory.BeanFactory;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.validation.BeanPropertyBindingResult;import org.springframework.validation.Errors;public class Teste { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/validate/Spring-beans.xml");
Pessoa p = (Pessoa) bf.getBean("pessoa");System.out.println("Nome: " + p.getNome() + " idade: " + p.getIdade());
Errors e = new BeanPropertyBindingResult(p,"Pessoa");p.validate(p, e);
for(Object es: e.getAllErrors()){ System.out.println(es);}
}}
Chamada manual !!!
• Wrapper de JavaBeans• Pattern GoF Decorator• Acesso a propriedade de objetos:
• Getters• Setters• Pode escrever?• Pode Ler?
• Acesso a sub-propriedades de profundidade ilimitada
• Manipulação com propriedades de maneira elegante
• Implementação padrão: BeanWrapperImpl
• PropertyDescriptor
• Customização de beans através de Callbacks
• Forma de extenção do Spring para:• Lógica de instanciação• Lógica de resolução de
dependências• Operações em geral após a
etapa de registro de beans do Spring
• Múltiplos BeanPostProcessors• Efetuar a ordem de execução
através da propriedade order, implementar a interface Ordered
• Atuação: Após a criação do bean• Executado antes de init-methods
• ApplicationContext: Registro automático
• BeanFactory: Registro manual
• São trados de maneira especial: “Toca inicializa”
ConfigurableBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
MeuBeanPostProcessor postProcessor = new MeuBeanPostProcessor();factory.addBeanPostProcessor(postProcessor);
• Cuidado com AOP Auto-proxy: Bean não elegíveis, Spring emitirá um alerta
• Veja um exemplo de BeanPostProcessor:package com.targettrust.spring.beanpostprocessors;public class ObjetoA {}
package com.targettrust.spring.beanpostprocessors;public class ObjetoB {}
package com.targettrust.spring.beanpostprocessors;public class ObjetoC {}
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;
}}
<?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" default-lazy-init="false"> <bean id="a" class="com.targettrust.spring.beanpostprocessors.ObjetoA" /> <bean id="b" class="com.targettrust.spring.beanpostprocessors.ObjetoB" /> <bean id="c" class="com.targettrust.spring.beanpostprocessors.ObjetoC" /> <bean class="com.targettrust.spring.beanpostprocessors.LogCreationBeanPostProcessor” />
</beans>
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/" + "beanpostprocessors/Spring-beans.xml");
}}
• Recebe o Objeto, então podemos:• Aplicar algum proxy• Aplicar algum validador• Poder: Annotations + interface
+ BeanPostProcessor
• Similar ao BeanPostProcessor• Pode ler metadados do Spring• Possibilidade de modificação de
dados(informações injetadas)• Spring utiliza no core:
• PropertyResourceConfigurer• PropertyPlaceHolderConfigurer
package com.targettrust.spring.beanfactorypostprocessors;import java.text.SimpleDateFormat;import java.util.Date;public class DataService {
private String pattern;public String getPattern() {
return pattern;}public void setPattern(String pattern) {
this.pattern = pattern;}
public String showSysDate(){SimpleDateFormat sdf = new SimpleDateFormat(pattern);return sdf.format(new Date());
}}
package com.targettrust.spring.beanfactorypostprocessors;import java.io.FileInputStream;import java.util.Map;import java.util.Properties;import 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 {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Properties p = new Properties(); try { p.load(new FileInputStream("./src/com/targettrust/spring/” +
beanfactorypostprocessors/patterns.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("#", ""))); } }}
<?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" default-lazy-init="false"> <bean id="brasilDateService" class="com.targettrust.spring.beanfactorypostprocessors.DataService" > <property name="pattern" value="#brasil" /> </bean> <bean id="usDateService" class="com.targettrust.spring.beanfactorypostprocessors.DataService" > <property name="pattern" value="#us" /> </bean>
<bean class="com.targettrust.spring.beanfactorypostprocessors.DatePatternRouterBeanFactoryPostProcessor" />
</beans>
package com.targettrust.spring.beanfactorypostprocessors;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Teste { public static void main(String[] args) { ApplicationContext ap = new ClassPathXmlApplicationContext("/com/targettrust/spring/beanfactorypostprocessors/Spring-beans.xml"); System.out.println("Data Brasil pattern : " + ((DataService)ap.getBean("brasilDateService")).showSysDate()); System.out.println("Data Us pattern : " + (DataService)ap.getBean("usDateService")).showSysDate());
}}
• Muito utilizado• Convertem a informação para o
tipo de dado correto.
• Deixa o XML menos verbose• Padroniza e prove produtividade
<bean id="txt" class="java.io.File"> <constructor-arg index="0" value="C:/BOOTSECT.BAK" /></bean>
• PropertyEditorManager(java, procurar)
• Localização automática• Foo• FooEditor• Extensível:
PropertyEditorSupport
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;}
@Overridepublic String toString() {
return nome;}
}
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;}
@Overridepublic String toString() {
return nome + " alunos: " + alunos.toString();}
}
package com.targettrust.spring.propertyeditor;import java.beans.PropertyEditorSupport;public class AlunoEditor extends PropertyEditorSupport{
@Overridepublic void setAsText(String text) throws IllegalArgumentException {
Aluno a = new Aluno(text);setValue(a);
}
}
<?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="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.CustomEditorConfigurer“ > <property name="customEditors"> <map>
<entry key="com.targettrust.spring.propertyeditor.Aluno"> <bean class="com.targettrust.spring.propertyeditor.AlunoEditor" /> </entry> </map>
</property> </bean></beans>
• Só no ApplicationContext• ApplicationEvent• ApplicationListener• Toda vez que um
ApplicationEvent é disparado seu ApplicationListener é notificado recebendo o evento.
• Sincronos (Bloqueio do Spring até o fim de todos)
package com.targettrust.spring.event;import org.springframework.context.ApplicationEvent;
public class FeriadoEvent extends ApplicationEvent{
private String data;private static final long serialVersionUID = 1L;
public FeriadoEvent(Object source,String data) {super(source);this.data = data;
}public String getData() { return data;}
}
package com.targettrust.spring.event;import org.springframework.context.ApplicationEvent;import org.springframework.context.ApplicationListener;
public class FeriadoListener implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent event) { if (event instanceof FeriadoEvent){
FeriadoEvent fe = (FeriadoEvent)event; System.out.println("Viva! Dia: " + fe.getData() + " é feriado. Uhhuu!!!" );}
}}
package com.targettrust.spring.event;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;
public class RH implements ApplicationContextAware {
private ApplicationContext ac;
public void pulicarFeriados(){ ac.publishEvent(new FeriadoEvent(this,"01/01/08"));}
@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ac = applicationContext;}
}
<?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="rh" class="com.targettrust.spring.event.RH" /> <bean id="funcionarioEsperto" class="com.targettrust.spring.event.FeriadoListener" />
</beans>
package com.targettrust.spring.event;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Teste {
public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/event/Spring-beans.xml");
RH rh = (RH)ac.getBean("rh"); rh.pulicarFeriados(); }}
• Externalizar informações na BF• É um BeanFactoryPostProcessor• Externalização em .properties• Útil para:
• Conexões de banco• Usuários• Listas de e-mails• Evita mexer no XML, diminui
erros
• Procura nas propriedades do sistema de modo: systemPropertiesMode
• Excelente para realizar roteamentos
• Diminui o volume de dados em XML
• Aceita Property em linha, dupla flexibilidade
package com.targettrust.spring.propertyplaceholderconfigurer;public class Instrutor {
private String nome;private int idade;private String time;private float altura;
// getters and Setters}
nome=deigoidade=22altura=1.85
Arquivo .properties
<?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 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location“> <value>classpath:com/targettrust/spring/propertyplaceholderconfigurer/config.properties </value> </property> <property name="properties"> <value>time=Grêmio</value>
</property> </bean> <bean
id="I”class="com.targettrust.spring.propertyplaceholderconfigurer.Instrutor" >
<property name="nome" value="${nome}" /> <property name="idade" value="${idade}" /> <property name="time" value="${time}" /> <property name="altura" value="${altura}" />
</bean></beans>
• Permite carregar múltiplos arquivos de configurações de uma só vez
• Aplicação dividida em camadas• Cuidado ao utilizar: veja JEE • Cada camada é uma BeanFactory• XML na raiz do cp com nome:
beanRefFactory.xml
package com.targettrust.spring.singletonbeanfactorylocator;public class ObjetoA {}
<?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" default-lazy-init="true"> <bean id="A1" class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA” /> </beans>
+ A2 A3 A4
<?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"default-lazy-init="false"
> <bean id="beanFactoryBean“class="org.springframework.context.support.ClassPathXmlApplicationContext”> <constructor-arg> <list> <value> com/targettrust/spring/singletonbeanfactorylocator/Spring-beans-A.xml </value> <value> com/targettrust/spring/singletonbeanfactorylocator/Spring-beans-B.xml </value> <value> com/targettrust/spring/singletonbeanfactorylocator/Spring-beans-C.xml </value> </list> </constructor-arg> </bean>
<bean id="beanFactoryBean2“ class="org.springframework.context.support.ClassPathXmlApplicationContext“ > <constructor-arg> <list>
<value> com/targettrust/spring/singletonbeanfactorylocator/Spring-beans-D.xml </value> </list> </constructor-arg> </bean></beans>
package com.targettrust.spring.singletonbeanfactorylocator;import org.springframework.beans.factory.access.BeanFactoryLocator;import org.springframework.beans.factory.access.BeanFactoryReference;import org.springframework.beans.factory.access.SingletonBeanFactoryLocator;public class Teste {
public static void main(String[] args) { BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance(); BeanFactoryReference bf = bfl.useBeanFactory("beanFactoryBean"); ObjetoA a1 = (ObjetoA)bf.getFactory().getBean("A1"); ObjetoA a2 = (ObjetoA)bf.getFactory().getBean("A2"); ObjetoA a3 = (ObjetoA)bf.getFactory().getBean("A3");
bf = bfl.useBeanFactory("beanFactoryBean2"); ObjetoA a4 = (ObjetoA)bf.getFactory().getBean("A4");
System.out.println("ObjetoA a1: " + a1); System.out.println("ObjetoA a2: " + a2); System.out.println("ObjetoA a3: " + a3); System.out.println("ObjetoA a4: " + a4); }}
• Somente no ApplicationContext• Procura por MessageSource• StaticMessageSource (padrão):
• Programaticamente• ResourceBundleMessageSource:
• Suporte textFormart• Carrega arquivos por nome
base• MessageSourceAware
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;
// Getters e Setters
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;
}}
idade.invalida= A idade: {0} não é aceitável por que é muito velha ou menor do que 1
<?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="messageSource“ class="org.springframework.context.support.ResourceBundleMessageSource“ > <property name="basenames"> <list> <value>mensagems</value> </list> </property> </bean>
<bean id="pessoa“ class="com.targettrust.spring.i18n.Pessoa“ />
</beans>
package com.targettrust.spring.i18n;import java.util.Locale;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Teste { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/i18n/Spring-beans.xml");
Locale.setDefault(new Locale("pt","BR"));setIdade(ac);
}
private static void setIdade(ApplicationContext ac){Pessoa p = (Pessoa)ac.getBean("pessoa");p.setNome("Crom");
try{ p.setIdade(200);}catch(RuntimeException re){ re.printStackTrace();}
}
}
1. Crie um objeto Pessoa: nome, idade, telefone.2. Crie um validador Pessoa3. Invoque o validador de pessoa em um BeanPostProcessor4. Externalize as mensagens de erro em um arquivo property e
mostre mensagens i18n caso a idade da pessoa esteja inválida.5. Crie um property editor que seja possível passar o nome, idade e
telefone da pessoa apenas na propriedade nome e o property editor espalhará as informações em suas propriedades corretas