Mentawai Web Framework

Inversão de Controle

OBS: Para um mini-tutorial sobre IoC acesse o link: http://forum.mentaframework.org/posts/list/193.page.

O Mentawai implementa de forma totalmente transparente um container de IoC bastante simples, mas não menos poderoso que os outros. Através do filtro global org.mentawai.filter.IoCFilter, você pode instanciar e injetar qualquer componente em suas action e/ou beans (POJOs). Abaixo temos um componente Talker que foi implementado de trê?s maneiras PortugueseTalker, UnpoliteTalker e PoliteTalker:


public interface Talker {
    
    public String saySomething();
    
}

public class PortugueseTalker implements Talker {
        

    public String saySomething() {
        
        return "from PortugueseTalker: Como está vc?";              
    
    }
        
        
}

public class UnpoliteTalker implements Talker {
    
    private String name;
    
    public UnpoliteTalker(String name) {
        this.name = name;
    }
    
    public String saySomething() {
        return "from " + name + " (" + toString() + "): Hello you #$#((%$#!";
    }
    
}

public class PoliteTalker implements Talker {
    
    private String name;
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String saySomething() {
        return "from " + name + " (" + toString() + "): Hello Sir!";
    }
    
}

Agora vamos analisar como podemos configurar esses componentes no nosso ApplicationManager.java:


public class ApplicationManager extends org.mentawai.core.ApplicationManager {
    
    public void init() {
        
        // Define the IoC components...
        
        ioc("talker1", PortugueseTalker.class);
        
        ioc("talker2", PoliteTalker.class)
            .addProperty("name", "Polite guy");
            
        ioc("talker3", UnpoliteTalker.class, SESSION)
            .addInitValue("Unpolite guy");
            
    }
    
    public void loadActions() {
        
        
        // IoC Global Filter...
        filter(new IoCFilter());
        
        // Injection filter to inject values straight into the action
        filter(new InjectionFilter());
    
        action("/HelloIoC", HelloIoC.class)
            .on(SUCCESS, fwd("/show.jsp"));
    }
}

Os componentes talker1, talker2 e talker3 serão injetados diretamente na action através de um método setter (Ex: setTalker1(Talker t)) ou diretamente dentro dos campos (Ex: Talker talker1). Quem controla e executa essa injeção é o InjectionFilter. Note que nada nos impede também de utilizar o IoCFilter sem o InjectionFilter, sendo a única diferença é que acessaremos os nossos componentes através do input da action, já que eles não serão injetados automaticamente pelo InjectionFilter.


public class HelloIoC extends BaseAction {
    
    private Talker talker1 = null;
    private Talker talker2 = null;
    private Talker talker3 = null;
    
    public void setTalker1(Talker t) {
        this.talker1 = t;
    }
    
    public void setTalker2(Talker t) {
        this.talker2 = t;
    }
    
    // t3 will be injected straight into the private field... (no need for setter)
    
    public String execute() throws Exception {
        String s1 = null;
        String s2 = null;
        String s3 = null;
        
        if (talker1 != null) {
            s1 = talker1.saySomething();
            output.setValue("from_t1", s1);
        }
        if (talker2 != null) {
            s2 = talker2.saySomething();
            output.setValue("from_t2", s2);
        }
        if (talker3 != null) {
            s3 = talker3.saySomething();
            output.setValue("from_t3", s3);
        }
        return SUCCESS;
    }
}

Se decidirmos por não usar o InjectionFilter, nossa action poderia ficar assim:


public class HelloIoC extends BaseAction {

    public String execute() throws Exception {
        
        Talker talker1 = (Talker) input.getValue("talker1");
        Talker talker2 = (Talker) input.getValue("talker2");
        Talker talker3 = (Talker) input.getValue("talker3");
        
        String s1 = null;
        String s2 = null;
        String s3 = null;
        
        if (talker1 != null) {
            s1 = talker1.saySomething();
            output.setValue("from_t1", s1);
        }
        if (talker2 != null) {
            s2 = talker2.saySomething();
            output.setValue("from_t2", s2);
        }
        if (talker3 != null) {
            s3 = talker3.saySomething();
            output.setValue("from_t3", s3);
        }
        return SUCCESS;
    }
}

Resumindo, as configurações de IoC do Mentawai são mínimas e tudo ocorre de forma automática e transparente. As principais características de um componente de IoC do Mentawai são:

  • Seus componentes podem ter três diferentes escopos: REQUEST, SESSION e APPLICATION. O IoCFilter do Mentawai controla de forma precisa a criação de instâncias de acordo com o escopo do componente.

  • Seus componentes podem ter propriedades configuráveis, que são setadas através do método addProperty().

  • Seus componentes podem ter construtores com parâmetros, que são setados através do método addInitValue().

  • Não há necessidade de interfaces enablers (facilitadores). A injeção é feita pelo InjectionFilter e pode se dar através de um método setter ou diretamente dentro de um campo (privado ou público).

Você também pode clicar aqui para baixar um exemplo de IoC.