[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 

Forum Read-Only! Check the new site and forum here!

1) O que é IoC e pra que serve o IoCFilter do Mentawai ?  XML
Forum Index -> F.A.Q.
Author Message
boaglio


[Avatar]

Joined: 28/09/2005 11:05:16
Messages: 299
Location: Sao Paulo - Brazil
Offline

1) O que é IoC e pra que serve o IoCFilter do Mentawai ?

Inversão de Controle é a arte de programar sem gerar acoplamentos entre as classes, isto é, uma classe não deve nunca instanciar outra classe dentro dela.

Ex:

Code:
 
 public class Carro {
 
    private final Motor1000 motor;
 
    public Carro() {
 
       this.motor = new Motor1000();
 
    }
 
 }
 


A classe Carro acima está fortemente acoplada a classe Motor1000. Algumas desvantagens desse exemplo são:

Se amanhã eu precisar trocar o motor do meu carro, terei que obrigatoriamente recompilar o código da classe Carro.

Um erro mais gritante é que a classe carro está acoplada a uma classe concreta e não a uma interface, o que é um atente contra as regras de flexibilidade e refatoração.

Para deixarmos a coisa totalmente flexível e desacoplada, poderíamos fazer assim:

Code:
 
 public interface Motor {
 
 // métodos comuns a todo motor aqui...
 
 }
 
 public class Motor1000 implements Motor {
 
    // implementação dos métodos da interface aqui...
 
 }
 
 public class Carro {
 
    private Motor motor;
 
    public Carro() {
 
    }
 
    public void setMotor(Motor motor) {
      
        this.motor = motor;
    }
 
 }
 
 


Note que agora a classe carro está acoplada a uma interface e não mais se preocupa em criar uma implementação de motor. Essa implementação será passada pra ela através do método setMotor() (setter).

Ex:

Code:
 
 Carro gol1000 = new Carro();
 gol1000.setMotor(new Motor1000());
 
 


Entretanto o código acima está novamente criando um acoplamento forte com new Motor1000(), ou seja, está instanciando uma classe concreta diretamente no código. Como escapar desse acoplamento então ? A solução é usar um container de IoC, ou seja, um serviço ou framework externo que se encarrega de criar e passar (injetar) a instância do seu objeto para um outro objeto que precisa dela.

O Mentawai é também um poderoso container de IoC, como veremos a seguir.

O primeiro passo é, ao invés de usar new para criar um objeto, usaremos um componente de IoC que, via reflection, se encarregará de nos fornecer instâncias da classe em questão:

Code:
 
 ioc("motor", Motor1000.class); // definindo o componente de IoC "motor"
 
 filter(new IoCFilter()); // filtro global que transforma o Mentawai num container de IoC
 
 // dentro da sua action vc pode fazer:
 
 Motor motor = (Motor) input.getValue("motor");
 
 


No código acima, tudo que estamos definindo é:

Temos um componente motor que vai gerar instancias a partir da classe Motor1000.class

Esse component (motor) é definido totalmente fora da sua aplicação, em outras palavras, ele é definido nas configurações do seu projeto (ApplicationManager.java).

O IoCFilter é um filtro global que transforma o Mentawai num poderoso container de IoC. Através dele, de forma totalmente automática e transparente, sempre que sua action requisitar o parâmetro "motor" do input, o Mentawai se encarregará de entregar uma instância correspondente ao componente em questão.

O IoCFilter é esperto o suficiente para gerenciar a criação das instâncias de acordo com o escopo do componente, como veremos mais abaixo. O escopo default é REQUEST, ou seja, quando não especificarmos um escopo, o escopo assumido será REQUEST.

Note que além de REQUEST, que é o escopo default, temos também outros dois escopos:

SESSION: A instancia irá persistir ao longo da session do usuário, ou seja, enquanto a sessão for a mesma, sucessivas chamadas ao método input.getValue("motor"); irão retornar a mesma instância.

APPLICATION: A instancia irá persistir durante toda a sua aplicação, ou seja, será a mesma até que sua aplicação seja restartada. (Quem precisa de singleton quando se tem IoC ???)

Note que mesmo para o escopo REQUEST, sucessivas chamadas ao método input.getValue("motor"); irão retornar a mesma instância, desde que estejamos dentro do mesmo request, ou seja, o container de IoC do Mentawai gerencia de forma precisa a criação de instâncias para cada escopo.

Para definirmos um componente de IoC com escopo, fazemos assim:

Code:
 
 ioc("motor", Motor1000.class, SESSION);
 
 // ou
 
 ioc("motor", Motor1000.class, APPLICATION);
 
 


Note também que nada nos impede de utilizar o InjectionFilter para injetar os componentes de IoC diretamente na sua action, ou seja, se sua action possui a propriedade "motor" o InjectionFilter se encarregará de injetá-la sem que vc precise acessar o input da action ou fazer qualquer coisa.

Outra coisa que devemos notar é que o InjectionFilter não impõe que a sua action defina um método setter (setMotor()) para receber o objeto que está sendo injetado. Esse injeção pode ser feita diretamente no campo, mesmo que esse seja privado. Veja o exemplo de uma action que recebe através do InjectionFilter o nosso motor.

Code:
 
 public class MinhaAction extends BaseAction {
 
    private Motor motor;
 
    public String execute() throws Exception {
 
       System.out.println("Ligando o motor...");
 
       motor.ligar();
 
    }
 
 }
 
 


Além de deixar o seu código bem mais limpo e claro, o grande barato de IoC é que se amanhã vc quiser mudar o seu motor, digamos para um motor 1.8, vc não precisa tocar no seu código. Tudo que vc precisa fazer é ir na sua configuração (ApplicationManager.java) e mudar uma linha de código:

Code:
 
 ioc("motor", Motor18.class);
 
 


Espero que vc tenha entendido o ganho de flexibilidade, organização e clareza que o IoC pode proporcionar aos seus projetos.

Um outro exemplo, utilizado na aplicação demo MyBooks, é usar IoC com DAO de forma que se amanhã vc quizer trocar de banco de dados, tudo que vc precisa fazer é reconfigurar os componentes de DAO para as novas implementações.

Ex:

Code:
 
 ioc("userDAO", MySqlUserDAO.class);
 
 // mudando para Oracle
 
 ioc("userDAO", OracleUserDAO.class);
 
 


Até a próxima!




http://www.boaglio.com
[WWW]
YkyMatt



Joined: 15/08/2007 15:47:05
Messages: 229
Location: RS / Brasil
Offline

Aí no código percebi que está sendo usado o método ioc. Entretanto, eu prefiro usar o estilo Java (more verbose) no ApplicationManager. Fui pesquisar na API e, pelo que vi, só há o método addComponent(String, Component), parece-me, portanto, que no Java Style eu sou obrigado a fazer meus objetos (o Motor, por exemplo) implementarem a interface Component de marcação?

Eu não costumo usar os métodos action, fwd, redir (less verbose) e, sendo assim, gostaria de não usar para IoC. Será que está faltando a sobrecarga do método correto: addComponent(String, Class)?

Jéferson C. Flores
Compusoft - Desenv. de Sistemas Empresariais

Mentawai Evangelist
http://www.chronusteam.com
[MSN]
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


Se quiser usar o JavaStyle aqui vc tem que fazer assim:

Code:
 addComponent(name, new DefaultComponent(klass));
 


Isso equivale a:

Code:
 
 ioc(name, klass);
 
 




Sergio Oliveira

YkyMatt



Joined: 15/08/2007 15:47:05
Messages: 229
Location: RS / Brasil
Offline

saoj wrote:

Se quiser usar o JavaStyle aqui vc tem que fazer assim:

Code:
 addComponent(name, new DefaultComponent(klass));
 


Isso equivale a:

Code:
 
 ioc(name, klass);
 
 

 


Obrigado!

Jéferson C. Flores
Compusoft - Desenv. de Sistemas Empresariais

Mentawai Evangelist
http://www.chronusteam.com
[MSN]
YkyMatt



Joined: 15/08/2007 15:47:05
Messages: 229
Location: RS / Brasil
Offline

Falta a sobrecarga do addComponent pra suportar a especificação de um escopo.

Falta algo como:

Code:
 public ScopeComponent addComponent(String name, Class<? extends Object> klass, int scope)
   { ioc(name, klass, scope); }
 

Jéferson C. Flores
Compusoft - Desenv. de Sistemas Empresariais

Mentawai Evangelist
http://www.chronusteam.com
[MSN]
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline

Esse carinha tá lá no código do Applicationmanager.java:

Code:
     public ScopeComponent ioc(String name, Class klass, int scope) {
 
         ScopeComponent c;
 
         addComponent(name, c = new ScopeComponent(klass, scope));
 
         return c;
     }
 


Sergio Oliveira

YkyMatt



Joined: 15/08/2007 15:47:05
Messages: 229
Location: RS / Brasil
Offline

saoj wrote:
Esse carinha tá lá no código do Applicationmanager.java:

Code:
     public ScopeComponent ioc(String name, Class klass, int scope) {
 
         ScopeComponent c;
 
         addComponent(name, c = new ScopeComponent(klass, scope));
 
         return c;
     }
 

 


Ah, legal! Thanks!

Jéferson C. Flores
Compusoft - Desenv. de Sistemas Empresariais

Mentawai Evangelist
http://www.chronusteam.com
[MSN]
 
Forum Index -> F.A.Q.
Go to:   
Powered by JForum 2.1.6 © JForum Team