terça-feira, 29 de setembro de 2009

Spring Framework - O que é afinal de contas e para onde ele vai?

A aquisição da SpringSource™ pela VMWare™ é um sinal da importância das idéias que estão por trás do Framework desenvolvido por Rod Johnson e sua trupe. Mas o que é esse framework e qual a sua importância para uma empresa que é um dos players principais nos conceitos de virtualização?

O grande apelo oferecido pelos desenvolvedores do Spring é a sua simplicidade no desenvolvimento bem como sua grande flexibilidade, o que, em conjunto com algumas ferramentas de apoio, fazem com que um código Java simples possa criar aplicações corporativas robustas e de fácil manutenção.

Mas como isso é possível, afinal?

As premissas básicas que estão por trás deste framework são simples:
  • Injeção de dependência
  • Programação Orientada a Aspecto
Mas o que é isso, afinal?

A Injeção de Dependência


Trata-se de um termo alcunhado pelo guru Martin Fowler e que de maneira simples pode se fazer o seguinte paralelo:

Para desenvolver eu dependo de algumas ferramentas (computador, monitor, software, teclado, mouse) sem o qual conseguiria criar um sistema.

Para resolver esse problema, poderia eu mesmo montar o computador (encaixando as placas, testando todos os componentes), instalar todos os softwares e conectar todos os cabos. Ufa que complicação! Mas não desenvolvi nada do sistema...

Outra possibilidade é a de alguém oferecer essa infra estrutura para mim montada (um fabricante ou a área de suporte, por exemplo) e poderia desenvolver o sistema sem grandes percalços.

Se alguém injetasse essas dependências que tenho para desenvolver como seria rápído o meu desenvolvimento!

O Spring oferece um micro servidor de aplicações (o conteiner de injeção de dependência) que é capaz de montar essas dependências, e entregá-las conforme necessidade. Ele precisa conhecer quais são as classes que serão gerenciadas e para isso necessita de um arquivo de configuração.

Nas versões mais recentes, esse arquivo deu uma emagrecida e pode ser visto a seguir:

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config />
<context:component-scan base-package="br.com.globalcode.spring" />  
</beans>

Nele, peço para ele varrer por um pacote especifico (br.com.globalcode.spring) e seus subpacotes para encontrar as classes que devem ser gerenciadas pelo Spring. Mas quais são essas classes?

Que tal o programador testar seu equipamento? Eis o programador:

package br.com.globalcode.spring;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component(value="programador")
public class Programador {

@Resource(name="computador")
private Computador computador;

private boolean desenvolvedorPronto;

public void testarComputador(){
computador.ligar();
computador.logar();
computador.desligar();
desenvolvedorPronto=true;
}
public boolean isDesenvolvedorPronto() {
  return desenvolvedorPronto;
}
}


Apelidei a classe Programador através da anotação @Component(value="programador")

Disse ao Spring que o desenvolvedor precisa de um computador (@Resource(name = "computador" ))

O Computador está aqui:

package br.com.globalcode.spring;

import org.springframework.stereotype.Component;

@Component(value="computador")
public class Computador {

public void ligar() {
System.out.println("Liguei");
}

public void logar() {
System.out.println("Fazer login");

}

public void desligar() {
System.out.println("Desliguei");  
} 
public void salvar() {
System.out.println("Salvar");

}

}

Para juntar as peças, peço para o conteiner do Spring seja inicializado, e que ele crie os objetos e os disponibilize em nosso código. Para isso, foi criado um teste simples:

package br.com.globalcode.spring;

import static org.junit.Assert.*;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FuncionarioTest {

private static ApplicationContext context;
@BeforeClass
public static void setUp(){
context = new ClassPathXmlApplicationContext("spring.xml");
}

@Test
public void testCriarProgramador() throws Exception {
Programador o = context.getBean("programador",Programador.class);
o.testarComputador();
assertTrue(o.isDesenvolvedorPronto());
}
}

No método setUp é carregado o arquivo de configuração do Spring, e no método testCriarFuncionario() é realizado a busca pelo programador no interior do conteiner. Ele encontra o "programador" e disponibiliza-o para o meu código o objeto do tipo Programador. Peço para chamar o método testarComputador, que em nosso intrépido programador ligava, logava e desligava o computador. E por fim avalio se o desenvolvedor está pronto para programar.

A Programação Orientada a Aspectos


Se ele consegue criar essa infra estrutura, é possivel incrementar as capacidades daquilo que fabrica também. Alguma coisa como um carro com motor mais potente, ou uma ferramenta mais robusta.

Se ele consegue fabricar objetos para montar a infra, posso instrumentá-la para incorporar novas funcionalidades. Alterar o código fonte sem modificar a estrutura do codigo (incorporação de aspectos) é algo que o Spring é capaz de fazer tornando ainda mais o seu codigo enxuto.

O meu computador deve gravar o codigo fizer qualquer operação no micro. Mas para viabilizar essa gravação automatizada, tenho que copiar e colar um código no final de todos os métodos, o que fere um principio chamado Don't Repeat Yourself (DRY).

Infelizmente não é possivel evitar essa cópia através da programação Orientada a Objetos e nesse momento a Programação Orientada a Aspectos brilha. No fundo se criarmos um código que será adicionado a todos os métodos existentes na classe Computador sem que eu tenha que copiar e colar seria o ideal. Isso é algo viabilizado através do conteiner de injeção de dependência na medida que ao construir os objetos ele consegue enxertar o código na minha aplicação.

Para isso vamos criar uma classe que faça essa operação toda vez que uma pessoa desligar o computador:

package br.com.globalcode.spring;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class SalvarAspecto {

@Around("execution(public * br.com.globalcode.spring.Computador.desligar(..))")
public Object gravar(ProceedingJoinPoint pjp) throws Throwable {
Computador computador = (Computador) pjp.getThis();
computador.salvar();
Object retVal = pjp.proceed();
return retVal;
}
}

Criamos uma classe que é diferenciada por uma annotation (@Aspect) .Nela identificamos a chamada de método desligar que existe na classe Computador(@Around). Nesse momento, o método gravar solicita ao computador que sejam gravadas quaisquer alterações.

A única mudança necessária éno arquivo de configuração que necessita uma referência ao uso da programação por aspectos.

<aop:aspectj-autoproxy proxy-target-class="true" /<

E a partir de agora ele consegue interceptar o momento de desligar o computador e antes de efetuar a operação é realizada a gravação daquilo que estiver ativo.
Note que se quisermos incorporar outros métodos podemos cadastrar no aspecto e não no código Java.Isso possibilita a ativação ou desativação sem que o código Java seja mudado.

Mas como posso usar tudo isso?

A maneira mais imediata a se entender como isso pode ajudar o desenvolvimento, é observar que essas premissas simples são usadas por um projeto do SpringSource™ chamado Spring ROO. Através dele, criamos projetos que se baseiam fortemente em programação orientada a aspecto (pois muitas operações de um sistema são muito similares e que poderiam ser extraidas em códigos externos). O código com a inteligência do sistema fica num conjunto de classes muito simples e de fácil leitura, o que garante uma manutenibilidade muito grande.

Como isso se encaixa com o contexto da VMWare™?


O Spring, pela sua natureza, consegue trabalhar em muitas JVM's usando-se de um projeto chamado Terracotta™ que pode ser usado num conjunto de servidores virtualizados e que garantem a escalabilidade de qualquer sistema desenvolvido em Spring/Hibernate.

Ao oferecer multiplas máquinas virtuais, a VMWare™ consegue garantir que esse código possa rodar um multiplos processadores, sem que o código tenha que conhecer dessa infra estrutura.

Isso garante um código simples de se manter e que é capaz de rodar em multiplas máquinas, fazem com que o Spring Framework se torne uma tecnologia bastante sedutora para criar aplicações escaláveis e que precisam de uma infra mais leve.

Essas idéias simples, mas revolucionárias, tem sido alvo de estudos e até foram incorporadas ao conjunto de tecnologias que Java padroniza (vide JSR299). E é uma das formas da VMWare em participar desse grupo de elite de desenvolvedores que fazem parte da Especificação de Java.

3 comentários:

Julio Viegas disse...

Oi Ricardo, tudo bem?

Primeiramente, grande post!

A aquisicao da SpringSource consolida a VMWare como player de PaaS, adicionando mais valor ao stack. Imagine VMs jah com arquitetura de desenvolvimento rica com varios utilitarios abordando diversos cenarios de demanda Java EE. Agregue a isso o Grails, que fornece esse ambiente com agilidade de desenvolvimento. Isso habilita players SaaS instalar sua app sem complicacoes de infra.

A tendencia hj eh utilizar desenvolvimento agil e integracao de tecnologias. Containers de IoC promovem isso. E o Spring em especial jah vem com integracoes para as principais tecnologias e suportes que orbitam Java EE. E jah estah consolidado em mercado.

Se tudo se consolida, isso pode diminuir mercado e opcoes? Acho que nao. Acho que isso facilita a gerencia de configuracao e permite maior acesso a infra pelo time de desenvolvimento. Eh o sonho de qualquer desenvolvedor diminuir a latencia de configuracao de infra. E opcoes vao surgir e serao consolidadas em algum futuro com padronizacao...

Eu acho que estamos vivendo um grande momento de mudanca de paradigma com a entrada de cloud. A historia mostra que a tecnologia tende a virar commodity, partindo principalmente do software mais basico. E nesse movimento eh bom ver o que serah relevante para o mercado e o que nao serah.

Abs,
JV -- julioviegas.com

Anônimo disse...

Onde fala sobre spring framework nesse artigo ?

blogdoricardo disse...

A minha duvida é: Por onde eu começo a aprender Spring,desevolvo java desktop usando swing,conheço de html e jsp, mais por onde eu começo com o spring?