SyntaxHighlighter

sexta-feira, 23 de agosto de 2013

Spring.NET: Uma introdução



O Spring.NET é um port para a linguagem .NET do famoso Projeto do Framework de integração, o Spring, da empresa SpringSource, atualmente uma empresa do grupo VMWare, para a linguagem Java, tal framework já é bastate consolidado no meio Java até por, na época de sua criação, implementar tecnologias que a linguagem não tinha como padrão em sua JDK, tecnoogias estas que atualmente já fazem parte de projetos da comunidade principalmente a CDI - Component Dependency Injection, que hoje é uma JSR na comunidade Java, sendo largamente implementada agora na versão 6 de seu JDK. O Spring Framework também deu início ao Projeto para o Enterprise JavaBeans 3.0 onde utiliza muitos padrões de projeto implementados no Spring Framework e o principal deles é justamente a Injeção de Dependências, sendo esta a base de sua integração. Porém, a mesma tecnologia sendo portada para .NET ainda não teve o mesmo sucesso e nem mesmo a mesma quantidade de adeptos.
Muito disso se deve a existência de outros frameworks e conteineres para injeção de dependências tais como: Ninject, Castle Windsor dentre outros já bastante conceituados no mundo .NET. O Spring.NET pode facilmente ocupar este espaço por ser um framework de "curta curva de aprendizado" o que implica que o mesmo é bem mais fácil de se aprender e de se executar e também, a injeção de dependências. A Injeção de Dependências é apenas um de seus vários módulos e é a sua base principal. Diante disso o Spring.NET tira toda a sua vantagem diante dos outros frameworks de Injeção de dependências porque o Spring.NET não faz só este trabalho, faz mais do que isso: integra desde Camada de Acesso a Dados à Camada de Apresentação, bem como Queue Messaging, WebServices, Integração com WCF e por aí vai, utilizando o Spring.NET como integrador de suas aplicações, ele permite e garante a estabildade permitindo ao desenvolvedor que não se preocupe com a sua infraestrutura: coleta de lixo, instanciação de objetos, performance e escalabilidade. Qual seria a vantagem de se usar o mesmo framework para Integrar todas as camadas? creio que todo desenvolvedor ou Arquiteto procura algo deste porte para sua aplicações, o que será decisivo para o uso ou não do Spring.NET será apenas a arquitetura e principalmente o custo e o tempo do Projeto. Entendendo bem como funciona a Injeção de Dependências, o desenvolvedor consegue dominar o Spring.NET por completo.

Os Módulos do Spring.NET
O Spring.NET detém 18 módulos de Integração que participam de todo o ciclo de vida de um projeto: de sua análise até os teste finais para entrega do software. Vamos listá-los:
- Arquitetura de Base
Esta arquitetura é a que sustenta o Spring.NET e sobre ela que as integrações são executadas.
1) Core - Núcleo principal que é utilizado como Container para Injeção de Dependências e as funcionalidades principais, que são as interfaces de uso para esta infraestrutura de Injeção.
2) AOP - Aspect Oriented Programming - Programação Orientada a Aspectos contendo suas Suporte a Modelo AOP, Infraestrutura utilizando o Padrão de Projetos Proxy e a Biblioteca Aspect Library. O Spring.NET é um dos poucos frameworks que pode ser utilizado como container AOP também, esta tecnologia na linguagem Java já é bastante consolidada e utilizada, por isso ela também foi trazida para o Spring.NET para que suas facilidades em Projetos também sejam exploradas pelas Equipes que utilizam o .NET.
- Arquiteturas implementadas pelo Spring.NET para integração.
São as arquiteturas de integração propriamente ditas na qual o Spring disponibiliza tendo esta integração sempre facilitada pela Injeção de Dependências. Temos os seguintes módulos:
a) Camada de Dados (Gerenciamento de Transação): NHibernate;
b) Mensageria (Messaging) (Utilizando sempre através do Microsoft MSMQ): Apache NMS, Tibco EMS;
c) Serviços (Abstração de Serviços Portáveis, ou seja, WebServices, SOA e afins): Enterprise Services, Web Services e Serviços WCF.
d) Camada de Apresentação: MVC
e) Teste Unitário: NUnit e MSTest
f) Scheduling ou Agendamento de Tarefas: Quartz.NET
Neste artigo, vamos implementar a Arquitetura básica e o Módulo de Core. Em artigos futuros falaremos de todos os Módulos e arquiteturas.


Imagem 1. Módulos do Spring.NET


A Imagem 1 nos dá uma impressão do tamanho deste framework e suas implementações internas.

Injeção de Dependências com o Spring.NET

O Spring.NET e seu assembly Spring.Core implementam a Injeção de Dependências utilizando os dois tipos existentes: via Setter e via Construtor. Tomemos como exemplo uma Classe que fará a persistência de um Cliente e uma Classe que será responsável por abrir a conexão com a Base de Dados. Para este exemplo usamos as Classes respectivamente: ClienteDAL e Conexao. Estas duas Classes nos farão compreender melhor os dois tipos de Injeção de Dependências existentes e como estes são utilizados pelo Spring.NET.
Injeção de Dependências via Construtor
Neste tipo de Injeção, A Classe injetada estará encapsulada dentro de um parâmetro que será passado ao construtor, lembrando que este parâmetro deve ser tipado com a Classe a ser injetada, como mostram os Trechos de Código 1 e 2:

Trecho de Código 1. Classe Conexao
 public class Conexao{ 
  #region Construtor
  //Digitando ctor e pressionando a tecla TAB duas vezes
  //O Visual Studio cria um construtor padrão      
  public Conexao() 
  {
     //Algoritmo para acesso ao Banco de Dados
  }
  #endregion
 }

Esta nossa Classe Conexão fará o acesso ao Banco de Dados e será necessária em nossa classe de persistência. Esta será injetada no construtor da Classe ClienteDAL via parâmetro tipado como Conexao. Como mostrado no Trecho de Código 2.

Trecho de Código 2. Injeção da Classe Conexão no construtor de ClienteDAL 
#region Propriedades
        /// <summary>
        /// Propriedade que será utilizada para Injeção via Construtor
        /// </summary>
        public Conexao conector { get; set; }
        #endregion

        #region Construtores

        public ClienteDAL()
        {

        }

        /// <summary>
        /// Construtor para Injeção de Dependências 
        /// via Construtor
        /// </summary>
        /// <param name="conexao"></param>
        public ClienteDAL(Conexao conexao)
        {
            this.conector = conexao;
        }
#endregion
 

Neste ponto, observando o construtor da classe ContatoDAL, podemos notar que o parâmetro chamado conexao está tipado com a nossa Classe Conexao, logo já temos a nossa injeção de dependências pronta para uso, o Spring.NET utiliza do padrão singleton juntamente com o Service Locator, ou seja, abre apenas uma instância desta Classe diretamente, caso a mesma não esteja instanciada, ela o é automaticamente, sempre que o construtor é ativado. O que torna o uso bastante racional. Pronto, agora você já pode usar seus métodos de persistência preocupando-se apenas com as operações de CRUD.
Injeção de Dependências via Setter
Nesta modalidade de Injeção de Dependências, utilizamos um "setter" para que nele possamos Injetar a Classe que proverá todo o serviço necessário. Como podemos ver no Trecho de Código 3.
Neste modo, podemos utilizar uma interface para enriquecer a nossa codificação, posto que no momento da implementação da Injeção, podemos fazer com que a Classe Injetada possa utilizar a interface facilitando a abstração em um ambiente de “Mundo Real”. Neste momento, vamos utilizar esta Injeção via Setter em uma Classe de Regra de Negócio que irá utilizara a Interface IClienteDAL para prover a injeção de dependências para ClienteDAL


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using IntroSpringNet.Modelo;

namespace IntroSpringNet.Persistencia
{
    public interface IClienteDAL
    {
        void Salvar(Cliente cliente);
    }
}

Agora que criamos a nossa interface, vamos criar usar um trecho de código para exemplificar esta injeção.
#region Propriedades

public IClienteDAL DAL { get; set; }

#endregion

#region Métodos

public Boolean CadastrarCliente(Cliente cliente)
{
  DAL.Salvar(cliente);
  return true;
}

#endregion


Podemos ver na que a propriedade DAL recebe a Interface IClienteDAL onde receberá a injeção de ClienteDAL. A Classe CadastrarCliente, utiliza DAL e não há a necessidade de instanciar o objeto, posto que o Spring já está controlando o objeto em seu contêiner via setter.
Como o Spring gerencia os Objetos para a DI.
O Spring.NET tem uma forma peculiar de gerenciar seus objetos, todos estes objetos são registrados em um arquivo .xml, ele pode ser os descritores do próprio .NET, ou seja, os arquivos .config – App.Config se standalone ou Web.Config se Web. Pode-se utilizar estes arquivos ou neste arquivos fazer um apontamento para outro XML, posto que o Spring.NET tem um cabeçalho bem peculiar, no Trecho de Código 4, temos um exemplo de arquivo .XML com header e configuração de gerência de objetos registrados. Sem este arquivo, o Spring.NET não poderá funcionar posto que nele estão todas as funcionalidades necessárias para que o contêiner seja inicializado e que o mesmo reconheça todos os objetos através do parsing, ou seja, o arquivo é totalmente validado antes de ser utilizado

Trecho de Código 4. Configuração do Spring.NET em arquivo de configuração XML
<configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler
               , Spring.Core"/>
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler
               ,Spring.Core"/>
    </sectionGroup>
  </configSections>
...
<spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <!-- Objetos para Injeção de Dependências -->
    <objects xmlns="http://www.springframework.net">
      <!-- Conexao -->
      <object name="Conexao" type="DAL.FonteDeDados.Conexao, DAL"/>
            
      <!-- ContatoDAL -->
      <object name="ContatoDAL" type="DAL.Persistencia.ContatoDAL, DAL">
        <constructor-arg ref="Conexao"/>
      </object>
      
      <!-- ManterContato -->
      <object name="ManterContato" type="BLL.Negocio.ManterContato, BLL">
        <property name="Dao" ref="ContatoDAL" />
      </object>
      
    </objects>
  </spring>
...

Dentro da tag configSection no início do arquivo, temos a tag sectionGroup, dentro desta temos mais dois sections com o atributo de name, estes atributos significam que neste arquivo temos o acesso ao Contexto e que nele também existem objetos a serem gerenciados pelo Conteiner de Injeção de Dependências. Com relação ao Contexto, significa que temos de chamar a interface IApplicationContext dentro de nossa aplicação para que o Spring.NET possa acessar as configurações deste arquivo para iniciar o contêiner de Injeção de Dependências.
Na seção que contêm a tag de nome Spring, temos a configuração e registro dos objetos que serão utilizados pelo contêiner de DI. Veremos este trecho mais de perto através do Trecho de Código 5.

Trecho de Código 5. Seção de Configuração do Spring e seus objetos
<spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <!-- Objetos para Injeção de Dependências -->
    <objects xmlns="http://www.springframework.net">
      <!-- Conexao -->
      <object name="Conexao" type="DAL.FonteDeDados.Conexao, DAL"/>
            
      <!-- ContatoDAL -->
      <object name="ContatoDAL" type="DAL.Persistencia.ContatoDAL, DAL">
        <constructor-arg ref="Conexao"/>
      </object>
      
      <!-- ManterContato -->
      <object name="ManterContato" type="BLL.Negocio.ManterContato, BLL">
        <property name="Dao" ref="ContatoDAL" />
      </object>
      
    </objects>
  </spring>
Nesta seção, a tag context logo abaixo do inicio da seção completa o que está presente na configSection do Trecho de Código 4, onde temos o atributo chamado object. Ambas context e resource estão interligados a esta configSection.
Com relação aos objetos gerenciados pelo Spring se encontra dentro da tag object que é registrada através de objects  onde tem o nome de serviço apontando para HTTP://www.springframework.net, neste momento, iniciando o registro das Classes no contêiner de DI do Spring.
Cada tag object contém alguns atributos, sendo os mais importantes name e type. Name recebe um valor qualquer, como uma identificação, ela não precisa ser igual ao nome da Classe, mas por convenção o segue apenas para questões de documentação caso existam muitos em um arquivo de gerenciamento. Já type, somos obrigados a colocar o nome completo da classe, seguido de uma virgula (,) e o nome do assembly,como visto no Trecho de Código 6.

Trecho de Código 6. Um objeto simples registrado.
<!-- Conexao -->
<object name="Conexao" type="IntroSpringNet.Persistencia.Conexao, IntroSpringNet"/>
O objeto em questão significa que para o Conteiner a Classe DAL.FonteDeDados.Conexao no Assembly DAL foi registrada com o nome de Conexao
 Caso a tag object só tenha estes registros signfica que é apenas uma Classe sendo apontada e nada mais. Porém, quando fazer as injeções via setter ou via Construtor precisamos colocar mais uma tag dentro de object para informar ao Spring que dentro desta Classe gerenciada, o contêiner ainda precisa efetuar a Injeção de Dependencias. No Trecho de Código 7, vemos um exemplo de Injeção via Construtor das classes criadas nos Trechos de Código 1 e 2.

Trecho de Código 7. Injeção via construtor registrada no arquivo de configuração do Spring.NET
<!-- ClienteDAL -->
<!-- Injeção via Construtor -->
<object name="ClienteDAL" type="IntroSpringNet.Persistencia.ClienteDAL, IntroSpringNet">
<constructor-arg ref="Conexao"/>
</object>
Este objeto registrado no Trecho de Código 7 pela sua implementação nos mostra que não é um objeto simples, na tag constructor-arg significa que a Classe informada tem um construtor e que o parâmetro injetado é a classe registrada com o nome de Conexao, pois ref significa “fazer referência a um objeto registrado no container”. Então caso a interface IApplicationContext registre o objeto de nome ClienteDAL, ele automaticamente registrará dentro da Classe ClienteDAL, em seu construtor o tipo do argumento será a classe que está atrelada ao nome Conexao e para nosso entendimento é o mesmo objeto registrado no Trecho de Código 6, ou o nosso objeto simples.
A diferença no registro via setter é que ao invés de constructor-arg apenas chamamos a tag property, apontando a propriedade onde a Classe é injetada no setter. Como nos mostra o Trecho de Código 8.

Trecho de Código 8. Injeção vai Setter registrada no contêiner do Spring.NET
<!-- ManterContato -->
<!-- Injeção via Setter -->
<!-- Injeta ClienteDAL dentro de DAL
 DAL é tipada pela interface, logo a mesma é preenchida por ClienteDAL
-->
<object name="ManterCliente" type="IntroSpringNet.Negocio.ManterCliente, IntroSpringNet">
  <property name="DAL" ref="ClienteDAL" />
</object>

Este objeto informa que a propriedade DAL receberá a injeção do objeto ClienteDAL mostrado no Trecho de Código 7.

Implementação do Acesso aos Objetos

Agora faremos com que todas estas configurações acima funcionem plenamente. Neste trecho, vamos utilizar a fachada IApplicationContext do Spring para acessar o contêiner de Injeção de Dependências. Como no exemplo do Trecho de Código 8.


Contato contato = new Contato();
contato.NomeCompleto = "Luis Gabriel Nascimento Simas";
contato.Email = "gabrielsimas@gmail.com";
contato.Linkedin = "http://br.linkedin.com/in/gabrielsimas/";
contato.Twitter = "@gabnascimento";
contato.Facebook = "http://www.facebook.com/luisgabrielsimas";

IApplicationContext di = ContextRegistry.GetContext();
IContatoDAL dal = (ContatoDAL)di.GetObject("ContatoDAL");

dal.Salvar(contato);

Em di, lemos o arquivo de configuração, em dal, carregamos o objeto gerenciável do arquivo de configuração que contém o id contendo o valor “ContatoDAL”, o mesmo objeto do Trecho de Código 7.

Conclusão

Neste artigo bastante introdutório sobre o Spring.NET, vimos um pouco de sua base principal, que é a Injeção de Dependências, em artigos futuros falaremos de cada um dos módulos do Spring.NET de forma bastante prática. 

Referências
Spring.NET Framework - http://www.springframework.net/
Documentação do Spring.NET - http://www.springframework.net/documentation.html
Injeção de Dependências/DI de Martin Fowler - http://www.martinfowler.com/articles/injection.html