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:
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:
Nele, peço para ele varrer por um pacote especifico (
Que tal o programador testar seu equipamento? Eis o programador:
Apelidei a classe Programador através da anotação
Disse ao Spring que o desenvolvedor precisa de um computador (
O Computador está aqui:
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:
No método setUp é carregado o arquivo de configuração do Spring, e no método
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:
Criamos uma classe que é diferenciada por uma annotation (
A única mudança necessária éno arquivo de configuração que necessita uma referência ao uso da programação por aspectos.
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.
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.
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
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.
Comentários
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