O objetivo deste artigo é discutir e apresentar uma aplicação desenvolvida em Java adotando o framework Spring. Inicialmente, serão abordados alguns detalhes técnicos, principalmente sobre as tecnologias e padrões adotados pelo Spring. Posteriormente, então, uma aplicação será desenvolvida, visando apresentar, na prática, a adoção deste framework.
Introdução
Para obter um entendimento completo sobre as características do Spring, faz-se necessário compreender, inicialmente, o padrão Inversion of Control (Inversão de Controle), e sua variação denominada Dependency Injection (Inclusão de Dependência). Martin Fowler, em seu artigo entitulado Inversion of Control, leva a um entendimento mais aprofundado sobre este padrão, entretanto, é importante abordar aqui alguns detalhes.
A inversão de dependência é o que torna uma simples biblioteca de classes diferente de um framework. Uma biblioteca consiste em um conjunto de classes que um usuário instancia e utiliza seus métodos. Após a chamada ao método, o controle do fluxo da aplicação retorna para o usuário. Entretanto, em um framework este fluxo é diferente. Para utilizar um framework, código próprio da aplicação deve ser criado e mantido acessível ao framework, podendo ser através de classes que estendem classes do próprio framework. O framework, então, realiza a chamada deste código da aplicação. Após a utilização do código da aplicação, o fluxo retorna para ele.
Martin Fowler exemplifica este conceito através de interfaces de interação com o usuário (GUI). Em Swing, por exemplo, você define os tratadores de eventos para os vários campos da tela, enquanto o framework (Swing) contém o loop principal da aplicação.
Finalizando, temos ainda o padrão Dependency Injection, idealizado por Martin Fowler, que trata-se de uma especialização do padrão Inversion of Control. Aplicações como Spring e PicoContainer, denominados de lightweight containers, adotam a inversão de controle, entretanto, todo framework utiliza-se de inversão de controle. A pergunta é, então, que tipo de inversão de controle o Spring, por exemplo, realiza? Afirmar que o Spring é um bom framework porque aplica a inversão de controle é um erro, já que qualquer framework deve aplicar este padrão. Para compreender melhor o padrão dependency injection, partiremos para exemplos mais práticos.
A Figura 01 apresenta um modelo, no qual pode-se entender melhor este padrão. Observe a interface MovieFinder, responsável em definir o comportamento padrão para classes que desejam gerenciar um cadastro de filmes. Logo abaixo encontra-se a classe MovieFinderImpl, que define uma implementação concreta da interface MovieFinder. Nesta classe encontram-se as implementações para cada método definido na interface MovieFinder. Têm-se, ainda, a classe MovieLister, que utiliza uma implementação da interface MovieFinder para realizar a busca de filmes para apresentar em um tocador(player) de vídeo. Observa-se, neste exemplo, a dependência existente entre MovieLister e MovieFinder. Esta dependência é resolvida pela classe Assembler, a qual gerencia a “injeção” de uma implementação de MovieFinder, neste exemplo a classe MovieFinderImpl, em um objeto MovieLister. Portanto, este padrão trata da inversão sobre como eles procuram por uma implementação de uma interface para resolver a dependência entre os objetos.
Caso a classe MovieLister instancie diretamente (através da chamada de new MovieFinderImpl) um objeto do tipo MovieFinder, perderemos a capacidade de tornar MovieFinder “plugável”. A interface MovieFinder é, portanto, um contrato ou um padrão a ser seguido por quem deseja criar “Buscadores” de filmes, de forma que um módulo separado, o Assembler, possa injetar esta implementação em MovieLister. Podemos, desta forma, criar programas no qual as partes que o compõem são plugins gerenciados pelo Assembler.
Basicamente, existem dois tipos de injeção de dependência: Constructor Injection e Setter Injection. No primeiro tipo, Constructor Injection, a dependência é resolvida através de um construtor do objeto a receber o objeto dependente.
public class MovieLister { } |
Listagem 01
A Listagem 01 apresenta este tipo de injeção de dependência, na qual a classe MovieLister define como parâmetro do seu construtor padrão um objeto do tipo MovieFinder. Neste contexto, o objeto Assembler resolverá a dependência entre os dois objetos passando para MovieLister uma implementação concreta de MovieFinder através do seu construtor.
class MovieLister { } |
Listagem 02
A Listagem 02, por sua vez, apresenta o tipo Setter Injection, no qual a dependência entre os objetos é resolvida pelo Assembler através de um método Setter no objeto MovieFinder.
Concluindo, a adoção destes dois padrões visa permitir ao desenvolvedor focalizar-se na implementação das características específicas da aplicação, delegando para um framework, como o Spring, a tarefa de especificar a dependência entre alguns objetos.
Spring Framework
Entendido os conceitos de Inversão de Controle e Injeção de Dependência, as características e formas de uso do Spring tornam-se mais simples. A Figura 2 apresenta a estrutura do Spring.

O módulo Spring Core representa as principais funcionalidades do Spring, no qual o principal elemento é o BeanFactory. Trata-se de uma implementação do padrão Factory, responsável em remover a programação de Singletons e permitindo o baixo acoplamento entre a configuração e a especificação de dependências, de sua lógica de programação.
O módulo Spring DAO provê uma camada de abstração para JDBC, eliminando grande parte da codificação necessária para interagir com um banco de dados. O módulo ORM, entretanto, provê integração do Spring com outros frameworks para persistência de objetos, como Hibernate e iBatis. Para prover uma implementação de Orientação a Aspectos que permite a definição de pointcuts e methods interceptors, existe o módulo Spring AOP.
Para prover funcionalidades específicas para projetos Web, tem-se o módulo Spring Web. São funcionalidades como componentes para upload de arquivos e suporte para utilização de Inversão de Controle neste tipo de aplicação. O módulo Spring MVC, entretanto, fornece uma implementação de framework Web, similar ao Struts.
Container de Inversão de Controle (IoC)
Inicialmente, é preciso entender o conceito, adotado pelo Spring, de beans. Para este framework, qualquer objeto que forma sua aplicação e que está sob controle do Spring, é considerado um bean. Enfim, um bean trata-se apenas de um objeto de sua aplicação e nada mais. O Container IoC é o responsável pelo gerenciamento destes beans.
Estes beans, entretanto, muitíssimo provavelmente possuem dependências entre si. Estas dependências são definidas através de metadados. O Container IoC obtém essas configurações e, partindo destas configurações, gerencia a dependência entre os beans. Neste contexto, a interface org.springframework.beans.factory.BeanFactory representa o Container IoC do Spring. Conforme explicitado anteriormente, uma implementação desta interface é responsável em realizar o trabalho do Assembler, apresentado na Figura 01. Existem diversas implementações de BeanFactory, sendo a XmlBeanFactory a implementação mais comum. Nesta, toda configuração de dependência entre os objetos é definida em um arquivo XML.
Aplicação de Exemplo
Para este exemplo será utilizada a versão 1.5 da JDK da Sun e a IDE Eclipse, em sua versão 3.2. A versão do Spring a ser adotada será a 2.0 Release Candidate 2. Trata-se de uma aplicação simples, na qual será possível cadastrar e listar clientes de uma empresa fictícia. Inicialmente, não adotaremos nenhuma interface web. Pretendemos, entretanto, apresentar uma solução mais completa, adotando outros frameworks, como o Struts, nos próximos artigos.

O diagrama de classes da Figura 03 apresenta as interfaces e classes que compõem esta aplicação. As interfaces ClienteDao e Sistema delimitam o comportamento de objetos que implementam a persistência de objetos Cliente e o acesso ao sistema, respectivamente. Neste contexto, temos ainda a classe ClienteHibernateDao, que implementa a interface ClienteDao, permitindo a persistência de objetos do tipo Cliente através do framework Hibernate (www.hibernate.org), e SistemaImpl que fornece uma implementação concreta para a interface Sistema.

O projeto estará conforme a estrutura de pacotes ilustrada na Figura 4. O pacote padrão da aplicação é br.com.imasters.spring. O pacote br.com.imasters.spring.beans contém as classes de negócio, neste caso, a classe Cliente. Finalizando o pacote br.com.imasters.spring.dao e br.com.imasters.spring.dao.hibernate sustentam as classes responsáveis pela persistência do sistema.
Clique na imagem para ampliar.

O Spring pode ser obtido no endereço http://www.springframework.org/, no link Downloads. A Figura 05 apresenta o projeto no Eclipse configurado com as classes do Spring. As outras bibliotecas que acompanham o pacote de distribuição do Spring são necessárias apenas caso algumas funcionalidades extras sejam utilizadas. Entretanto, observar a necessidade de ter as bibliotecas commons-logging.jar e log4j.jar no classpath.
| public class Cliente { private int id ; private String nome ; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } |
Listagem 03
A Listagem 03 apresenta a classe Cliente, contendo apenas dois campos: id e nome. A Listagem 04 demonstra os métodos existentes na interface ClienteDao(Listagem 4), e que são implementados na classe ClienteDaoHibernate. Vamos manter o conteúdo desta classe simples, pois o objetivo deste artigo não é apresentar o Hibernate, e sim o funcionamento do Spring. Portanto, a listagem 08 apresenta esta classe apenas enviando mensagens ao console, através da chamada a System.out.println.
| public interface ClienteDao { Collection getClientes() ; void incluirCliente ( Cliente cliente ) ; } |
Listagem 04
A interface Sistema, e sua implementação SistemaImpl são apresentadas nas Listagens 5 e 6, respectivamente. Pode-se observar, neste exemplo, que a classe SistemaImpl apenas repassa as chamadas de seus métodos para métodos semelhantes da interface ClienteDao.
public interface Sistema { Collection getClientes() ; } |
Listagem 05
É possível observar que a classe SistemaImpl funciona conforme o padrão Facade, fornecendo um único caminho de entrada para o sistema, evitando que o usuário perca-se na complexidade inerente de todo sistema.
public class SistemaImpl implements Sistema { public Collection getClientes() { public void incluirCliente(Cliente cliente) { public ClienteDao getDaoCliente() { public void setDaoCliente(ClienteDao daoCliente) { } |
Listagem 06
Falta, ainda, definir a configuração de dependência entre os objetos desta aplicação. Para isto, criamos um arquivo chamado applicationContext.xml, e o colocamos no classpath da aplicação. A Listagem 07 apresenta o conteúdo deste arquivo. Neste arquivo, definimos o bean ClienteDao, como sendo do tipo br.com.imasters.spring.dao.hibernate.ClienteHibernateDao.
<?xml version="1.0" encoding="UTF-8"?> <beans> |
Listagem 07
Definimos também o bean Sistema, do tipo br.com.imasters.spring.SistemaImpl e que possui uma propriedade clienteDao que deve ser injetada com um objeto definido no bean ClienteDao.
public class ClienteHibernateDao implements ClienteDao { public Collection getClientes() { public void incluirCliente(Cliente cliente) { } |
Listagem 08
Finalmente, precisamos ativar o container IoC, de forma que as dependências entre os objetos possam ser resolvidas. A Listagem 09 encarrega-se de apresentar a classe Aplicacao.java, responsável por invocar o framework.
public class Aplicacao { public static void main ( String[] args ) { } |
Listagem 09
Conclusão
O principal objetivo deste artigo foi apresentar o framework Spring, o qual acredito ter sido cumprido. Muitos questionam a real necessidade de utilizar o Spring, já que padrões como Abstract Factory fornecem um nível de abstração próximo ao que o Spring fornece. Entretanto, o Spring permite que sua aplicação seja extremamente “plugável”, em runtime. A inserção de uma nova biblioteca e a alteração do arquivo applicationContext.xml é o suficiente para alterar uma estratégia de persistência, por exemplo. Com padrões como AbstractFactory, para conquistar este mesmo feito é necessário, pelo menos, realizar a recompilação de todo o código fonte.
Felizmente, o Spring não limita-se apenas a fornecer a Dependency Injection, é possível facilitar a criação de aplicações de muitas outras formas, como pela adoção dos módulos de ORM, ou JDBC. Entretanto, pretendemos manter este assunto para um próximo artigo.
Charles Souza
mas poderia usar generics
espero ansioso pelo proximo
flw
2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.