Spring
Inversão de Controle, Desenvolvimento
leve, Orientação a aspectos, ...
Ricardo Cavalcanti
[email protected]
Jobson Ronan
[email protected]
O que é?

Spring é um framework “leve” de
inversão de controle(IOC) e
orientação a aspectos(AOP)
Torna o desenvolvimento de aplicações
J2EE mais fácil e interessante!
Como assim?

Como Spring ajuda os desenvolvedores J2EE:




Oferece um container leve de JavaBeans que elimina a
necessidade de escrever códigos repetitivos “de
encanador” como lookups
Oferece um framework de inversão de controle que
permite as dependências dos beans serem descobertas
durante a instanciação
Permitir que cross cutting concers como gerenciamento
de transações ser aplicado aos beans como Aspectos ao
invés ser escrito no objeto de negócio
Oferecer camadas de abstração sobre tecnologias
populares como JDBC e Hibernate que facilite seu uso e
organize o gerenciamento de configuração
Como é?

Tudo isso seguindo alguns principios:

O Código de sua aplicação não deve depender
da API do Spring

Spring não deve competir com boas soluções
existentes mais sim promover integração

Escrever código testável é crítico e o container
deve ajudar(não interferir) nesse objetivo

Usar o Spring deve ser empolgante
Visão geral
Sobre a arquitetura

Spring pode ser usado em uma variedade
de situações

Aplicações web

Aplicações que envolvem EJBs ou outros
serviços

Aplicações que acessem uma ou mais
recursos(BDs)
Sobre a arquitetura

Apesar disso, Spring lidera os chamados
frameworks para o Desenvolvimento
“leve” de aplicações J2EE

Realmente precisamos de serviços pesados,
como EJB, providos pelos tradicionais
Servidores de aplicação J2EE?
Mas o que é IOC?


Um modo de remover as dependências
entre os objetos “injetando” as referências
para os colaboradores sobre demanda
(Dependency Injection)
O framework de IOC determina como os
objetos serão injetados, normalmente
através de um arquivo de configuração
XML
Benefícios




Remove a responsabilidade de encontrar ou criar
objetos dependentes, movendo-a para a
configuração
Reduz o acoplamento entre implementações de
objetos e encoraja o design baseado em
interfaces
Permite a aplicação ser reconfigurada fora do
código
Pode encorajar a escrever código “testável”
Modo tradicional
...
private AccountService accountService = null;
public void execute(HttpServletRequest req, ...) throws Exception {
Account account = createAccount(req);
AccountService service = getAccountService();
service.updateAccount(account);
}
private AccountService getAccountService() throws ... {
if (accountService == null){
Context ctx = new InitialContext();
Context env = (Context)ctx.look p("java:comp/env");
Object obj = env.lookup("ejb/AccountServiceHome");
AccountServiceHome home = (AccountServiceHome)
PortableRemoteObject.narrow(env,Acco ntService.class);
accountService = home.create();
}
return accountService;
}
...
Modo tradicional

Ainda podemos usar padrões de
projeto como “Service Locators” ou
“Factories”
Modo Spring
Com Spring, o container de IOC ira cuidar
da injeção de uma apropriada
implementação
..
private AccountService accountService = null;
public void setAccountService(AccountService accountService){
this.accountService = accountService;
}
public void execte(HttpServletRequest req, ...) throws Exception {
Account account = createAccount(req);
accountService.updateAccount(account);
}
...
Conceitos de AOP

Aplicações devem estar possuir interesses
como:




Gerenciamento de transações
Logging
Seurança
Essas responsabilidades devem pertencer
a implementação das classes?

Nossa classe AccountService deve ser ser
responsavel pelo gerenciamento de transação,
logging e segurança?
Conceitos de AOP

Implementação tradicional com todos
estes interesses
//...
public class AccountService {
public void updateAccount(updateAccount acount) throws Exception {
SecurityManager.requireUserRole(“admin”);
TransactionManager.beginTransaction();
try {
//...código de negócio
TransactionManager.commit();
log.info(“acount updated”);
} catch (Exception e) {
TransactionManager.rollback();
log.warning(“exception throw”, e);
throw e;
}
}
///...
Segurança
Transações
Logging
Conceitos de AOP


Esses interesses são chamados de
interesses atravessadores (Cross cutting
Concerns)
Sua implementação atravessa a
implementação de toda uma classe ou até
mesmo várias classes (como logging)
Conceitos de AOP

Com AOP separamos esses interesses e
definimo-os como um advice





Before Advice
After Advice
Around Advice
Throws Advice
E baseado em certos critérios (Pointcuts),
estes são inseridos na aplicação (Weaver)
Tipos de AOP

AOP Estático

Aspectos são tipicamente introduzidos ao byte code em
tempo de compilação ou através de classloaders
customizados em tempo de execução
• AspectJ (byte code)
• JBoss AOP, AspectWerkz (classloader)

AOP Dinâmico



Cria proxies para todos os objetos interessados
Leve perda de performance
Fácil de configurar
• Spring
Em detalhes...
O Container de Beans do Spring
O Container de Beans





É o núcleo do Spring famework
Usa IOC para gerenciar os componentes
que compõem uma aplicação
Componentes são expressos como simples
Java Beans
O Container gerencia as relações entre os
Beans e é responsável por sua
configuração
O Container controla o ciclo de vida dos
Beans
Tipos de Containers

Bean Factory



Dá suporte básico a injeção de dependência
Configuração e gerenciamento do ciclo de vida
Application Context

Construido sobre o Bean Factory adicionando
serviços de:
• Resolução “mensagens” através de arquivos de
propriedades para internacionalização
• Carregamento de recursos genéricos
• Publicação de eventos
Bean Factory
public interface Greeting {
String greeting();
}
public class WelcomeGreeting implements Greeting {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String greeting() {
return message;
}
}
Bean Factory
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id=“greeting” class=“WelcomeGreeting”>
<property name=“message”>
<value>Bem vindos</value>
</property>
</bean>
</beans>
...salvo em um arquivo chamado, por exemplo,
myapp-config.xml
Bean Factory
...
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(
new FileSystemResource(“myapp-config.xml”));
Greeting greeting = (Greeting) factory.getBean(“greeting”);
System.out.println(greeting.greeting());
}
Saída no console:
Bem vindos
Bean Factory

Características dos managed beans


Singletons por default
Propriedades setadas por Dependency
Injection
•
•
•
•
•

Referência para outros managed beans
Strings
Tipos primitivos
Coleções (lists, sets, map, props)
Inner Beans
Parâmetros podem ser extraídos para arquivos
de propriedades
Spring como suporte a camada de
negócio
Spring DAO + Spring ORM
O que temos?

Uma camada de abstração para persistência de dados
utilizando um ou mais das seguintes tecnologias





JDBC
Hibernate, OJB
JDO
iBatis
Uma robusta infra-estrutura para o gerenciamento de
transações de forma declarativa que suporta tanto
transações locais como transações distribuídas através da
JTA

Uma camada simplificadora para tecnologias de distribuição
incluindo EJBs, RMI, e Web Services

Útil suporte a JNDI, JMS, email, e agendamento de
tarefas(task scheduling)
Spring DAO



Possui uma API de acesso a dados que ajuda a
isolar e melhorar o modo como o dado é servido
pela camada de negócio
Mais uma consistente e rica hierarquia de
exceções suficiente para mapear exceções
específicas dependentes de tecnologia para
outras exceções genéricas
Além de uma série de templates e wrapper
classes para se trabalhar com JDBC, Hibernate,
JDO, etc.
JDBC Tradicional
public void updateCustomer(Customer customer) {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getConnection();
ps = conn.prepareStatement(“update customer set ” +
“firstName = ?, lastName = ?, ...”);
ps.setString(1, customer.getFirstName());
ps.setString(2, customer.getLastName());
ps.executeUpdate();
} catch (SQLException e) {
log.error(e);
} finally {
try { if (ps != null) ps.close(); }
catch (SQLException e) {log.error(e);}
try {if (conn != null) conn.close();}
catch (SQLException e) {log.error(e);}
}
}
private Connection getConnection() {
//... Mais código de encanador
}
Spring DAO

Usando um template jdbc do spring
public void updateCustomer(Customer customer) {
String sql = “update customer set ” +
“firstName = ?, lastName = ?, ...”);
Object[] params = new Object[] {
customer.getFirstName(),
customer.getLastName(),
...};
int[] types = new int[] {
Types.VARCHAR,
Types.VARCHAR,
...};
jdbcTemplate.update(sql, params, types);
}
O jdbcTemplate pode ser injetado pelo container...
Spring DAO

Operações também podem ser modeladas
como objetos
public class UpdateCustomer extends SqlUpdate {
public UpdateCustomer(DataSource ds) {
setDataSource(ds);
setSql(“update customer set… values (?,?..)”);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
//...
compile();
}
public int update(Customer customer) {
Object[] params = new Object[] {
customer.getFirstName(),
customer.getLastName()
};
return update(params);
}
}
Spring DAO

Usando o objeto UpdateCustomer
public class JdbcCustomerDao extends JdbcDaoSupport
implements CustomerDao {
private UpdateCustomer updateCustomer;
protected void initDao() throws Exception {
super.initDao();
updateCustomer = new UpdateCustomer(getDataSource());
}
public void updateCustomer(Customer customer) {
updateCustomer.update(customer);
}
}
A classe UpdateCustomer pode ser uma inner class
Integração ao Hibernate





Spring prove um bean SessionFactory que
simplifica a configuração e o gerênciamento de
sessões em objetos de negócio
Uma classe HibernateTemplate
Uma classe HibernateDaoSupport que pode ser
herdada para maior abstração
Gerenciamento e mapeamento das
HibernateException´s
Facilmente plugável ao framework de Transações
do Spring
Integração ao Hibernate

Exemplo de configuração
...
<beans>
<bean id=“sessionFactory” class=“org.springframework.orm.
hibernate.LocalSessionFactoryBean”>
<property name=“dataSource”>
<ref bean=“dataSource”/>
</property>
<property name=“hibernateProperties”>
<props>
<prop key=“hibernate.dialect”>
net.sf.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
<property name=“mappingResources”>
<list><value>Customer.hbm.xml</value></list>
</property>
</bean>
Continua...
Integração ao Hibernate

Exemplo de configuração (cont)
<bean id=“customerDao” class=“HibernateCustomerDao”>
<property name=“sessionFactory”>
<ref bean=“sessionFactory”/>
</property>
</bean>
<bean id=“dataSource” class=“org.springframework.jndi.
JndiObjectFactoryBean”>
<property name=“jndiName”>
<value>java:comp/env/jdbc/myDataSource</value>
</property>
</bean>
Integração ao Hibernate

Customer DAO...
public class HibernateCustomerDao extends HibernateDaoSupport
implements CustomerDao {
public void updateCustomer(Customer customer) {
getHibernateTemplate().update(customer);
}
}


Simples e limpo!
Existe suporte semelhante para outras
tecnologias ORM como iBatis, JDO e OJB
Transações com Spring




Suporte para gerenciamento programático
e declarativo de transações
Transações locais são delegadas pelo
Spring para o gerente de transações do
data-source
Quando múltiplos recursos estão
involvidos (transações distribuídas),
Spring delega para o gerente de
transações JTA obtido através do JNDI
Apenas algumas pequenas mudanças são
necessárias para trocar entre local e JTA
Transações com Spring

Gerenciamento Declarativo (+)


Usa AOP para encapsular chamadas a objetos
transacionais com código de begin e commit
de transações
Comportamento de propagação
• Mandatory, Never, Not Supported, Required, Requires
New, Support, Nested
• Similar a EJBs

Também suporta níveis de isolação
• Default, Read Uncommitted, Read Committed,
Repeatable Read, Serializable
Transações com Spring

Declarando atributos
Comportamento
de propagação
Transação somente
de leitura?
[opcional]
PROPAGATION, ISOLATION, readOnly, -Exceptions, +Exception
Grau de
isolamento
[opcional]
Os atributos são declarados no arquivo de
definição dos beans
Regras de
Rollback
[opcional]
Transações com Spring

Exemplo
...
<beans>
<bean id=“customerService” class=“org.springframework.transaction.
interceptor.TransactionProxyFactoryBean”>
<property name=“transactionManager”>
<ref bean=“transactionManager”/>
</property>
<property name=“target”>
<ref bean=“customerServiceTarget”/>
</property>
<property name=“transactionAttributes”>
<props>
<prop key=“get*”>PROPAGATION_REQUIRED, readOnly</prop>
<prop key=“store*”>PROPAGATION_REQUIRED</prop>
</props>
</property>
<bean>
...
Continua...
Transações com Spring

Exemplo (cont)
...
<bean id=“customerServiceTarget” class=“CustomerServiceImpl”>
<property name=“customerDao”>
<ref bean=“customerDao”/>
</property>
</bean>
<bean id=“transactionManager” class=“org.springframework.orm.
hibernate.HibernateTransactionManager”>
<property name=“sessionFactory”>
<ref bean=“sessionFactory”/>
</property>
</bean>
<bean id=“customerDao” class=“HibernateCustomerDao”>
<property name=“sessionFactory”>
<ref bean=“sessionFactory”/>
</property>
</bean>
...
AOP com Spring

Em prática
public interface IBusinessLogic {
public void foo();
}
public class BusinessLogic implements IBusinessLogic {
public void foo() {
System.out.println( “Inside BusinessLogic.foo()” );
}
}
AOP com Spring

Em prática
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class MainApplication {
public static void main(String [] args) {
// Read the configuration file
ApplicationContext ctx =
new FileSystemXmlApplicationContext("springconfig.xml");
//Instantiate an object
IBusinessLogic testObject = (IBusinessLogic)
ctx.getBean("businesslogicbean");
// Execute the public
// method of the bean
testObject.foo();
}
}
AOP com Spring



Uma vez que nossa MainApplication chama o
método ctx.getBean() ela abre mão da
instanciação e gerênciamento do Bean para o
Spring
Controlando a inicialização do nosso objeto, o
Spring implementa todas as tarefas de
gerenciamentos requeridas por aplicações J2EE
Isso, claro, antes que nosso objeto seja utilizado
pela aplicação
AOP com Spring

springconfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Bean configuration -->
<bean id="businesslogicbean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>IBusinessLogic</value>
</property>
<property name="target">
<ref local="beanTarget"/>
</property>
</bean>
<!-- Bean Classes -->
<bean id="beanTarget" class="BusinessLogic"/>
</beans>
AOP com Spring

Diagrama de seqüência
AOP com Spring

Implementando um Advice
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class TracingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method m, Object[] args,
Object target) throws Throwable {
System.out.println("Hello world! (by " +
this.getClass().getName() + ")");
}
}
AOP com Spring

Para acoplar o Advice a determinados
joinpoints de nossa aplicação prescisamos
acrescentar algumas declarações no
springconfig.xml
...
<!-- Advisor pointcut definition for before advice -->
<bean id="theTracingBeforeAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="theTracingBeforeAdvice"/>
</property>
<property name="pattern">
Aplicado por
<value>.*</value>
</property>
expressões regulares!
</bean>
<!-- Advice classes -->
<bean id="theTracingBeforeAdvice" class="TracingBeforeAdvice"/>
...
AOP com Spring

springconfig.xml (cont.)
<!-- Bean configuration -->
<bean id="businesslogicbean"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>IBusinessLogic</value>
</property>
<property name="target">
<ref local="beanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>theTracingBeforeAdvisor</value>
</list>
</property>
</bean>
AOP com Spring

Diagrama de seqüência
Chamada transparente ao Advice do aspecto
AOP com Spring

Existem ainda outras formas de
aplicar aspectos com o Spring

AutoProxy:
• BeanNameAutoProxyCreator
• DefaultAdvisorAutoProxyCreator
Exercício
Implemente o exemplo “greeting”
 Implemente um cadastro de usuários
usando hibernate + Spring

Cadastrar
 Remover
 Atualizar
 procurar

Exercícios (++)
Implemente DAOs para os objetos do
modelo do projeto Java Avançado
 Implemente uma fachada para o
sistema(SessionFacade) tratando as
transações de forma declarativa
 Implemente, utilizando AOP, o
logging de todas as exceções
lançadas pelos DAOs

Download

j2ee_pcc_Spring