GuiceでHello Worldを試してみた

Googleがリリースした超軽量、次世代型のDIコンテナという謳い文句のGuiceHello Worldを試してみました。違いがわかるようにSeasar付属のexample, Greeting(http://s2container.seasar.org/en/DIContainer.html#Quickstart)をGuiceで動くようにしてみました。まだ、あまりプログラミングの参考にできるWebサイトがないのですが、ここ(http://paulbarry.com/articles/2007/03/12/guice-hello-world)はとてもわかりやすくて助かりました。ユーザーズガイド(http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8)というものもあるのですが、これだけでは何からどうはじめていいのかわかりませんでした。

Greetingインタフェース、その実装のGreetingImplクラス、GreetingClientインタフェースまではまったく同じです。

//Greeting.java
public interface Greeting {
    String greet();
}

//GreetingImpl.java
public class GreetingImpl implements Greeting {
    
    public GreetingImpl() {
    }
    
    public String greet() {
        return "Hello World!";
    }
}

//GreetingClient.java
public interface GreetingClient {
    void execute();
}

GreetingClientインタフェースの実装ではGreetingの実装を参照したいので、そこに@Injectアノテーションを使うことになります。

//GreetingClientImpl.java
import com.google.inject.Inject;

public class GreetingClientImpl implements GreetingClient {
    private Greeting greeting;
    
    public GreetingClientImpl() {
    }
    
    public void execute() {
        System.out.println(greeting.greet());
    }

    @Inject
    public void setGreeting(Greeting greeting) {
        this.greeting = greeting;
    }
}

さらに、GreetingClientの実装をinjectionして参照するためのクラスGreetingControllerをひとつ作りました。これが本当に必要なのかどうか疑問なのですが、このクラスがないとMainクラスで行ったinjection開始のきっかけを作れないような気がしたので、参考にした例にしたがって作りました。

//GreetingController.java
import com.google.inject.Inject;

public class GreetingController {
    private GreetingClient greetingClient;
    
    public GreetingController() {
    }
    
    public void execute() {
        greetingClient.execute();
    }
    
    @Inject
    public void setGreetingClient(GreetingClient greetingClient) {
        this.greetingClient = greetingClient;
    }  
}

そして、Mainクラスです。このクラスでは最初にいわゆるコンテキスト取得を行って、その際にbindメソッドを使ってインタフェースと実装クラスの対応を指定しています。その後、Injectors#injectMembers()メソッドを実行してinjectionを開始するということを行っています。bindメソッドを使わなくても、@ImplementedByアノテーションをインタフェースに付ければいいという方法もありました。bindメソッド実行時にはインスタンスのscopeも指定できるようになっていました。アプリケーションの場合、まだSINGLETONしかありませんが、サーブレットにはSESSIONとREQUESTがあります。

// Main.java
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Guice;

public class Main {

    public Main() {
        Injector injector = Guice.createInjector(new GreetingModule());
        GreetingController controller = new GreetingController();
        injector.injectMembers(controller);
        controller.execute();
    }

    public static void main(String[] args) {
        new Main();
    }
    
    private class GreetingModule extends AbstractModule {
        protected void configure() {
            bind(Greeting.class).to(GreetingImpl.class);
            bind(GreetingClient.class).to(GreetingClientImpl.class);
        }
    }
}

Guiceはまったくコンフィギュレーションを書かないですし、シンプルなので比較的わかりやすいかもしれません。ただ、今のところほんとうにシンプルな機能しかないので、これでユーザは満足できるのか?と疑問に思いました。とはいってもごく簡単なサンプルをひとつ作ってみただけですし、Guiceもリリースされたばかりでこれから発展していくでしょうからこれだけではまだ判断できないかも、です。