Author |
Message |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 25/08/2006 19:46:47
|
boaglio
![[Avatar]](/images/avatar/3416a75f4cea9109507cacd8e2f2aefc.jpg)
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
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 19/08/2007 19:08:20
|
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 |
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 21/08/2007 10:26:48
|
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:
|
Sergio Oliveira
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 21/08/2007 11:36:31
|
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:
Obrigado!
|
Jéferson C. Flores
Compusoft - Desenv. de Sistemas Empresariais
Mentawai Evangelist
http://www.chronusteam.com |
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 24/08/2007 15:40:05
|
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 |
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 24/08/2007 15:44:14
|
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
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 24/08/2007 15:45:38
|
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 |
|
 |
|
|
|