CALENDAR
S M T T F S
    123
45678910
11121314151617
18192021222324
25262728293031
<< October 2020 >>
ARCHIVES
CATEGORIES
RECOMMEND
RECOMMEND
Javaデザインパターン徹底攻略 (標準プログラマーズライブラリ)
Javaデザインパターン徹底攻略 (標準プログラマーズライブラリ) (JUGEMレビュー »)
日立ソフトウェアエンジニアリングインターネットビジネス部
RECOMMEND
RECOMMEND
独習Java第3版
独習Java第3版 (JUGEMレビュー »)
ジョゼフ・オニール
MOBILE
qrcode
Guice
googleからでているDIコンテナGuiceです

入手先はこちら(ver3.0 4.0はBeta版らしい)

ということで早速手に入れコーディングしてみた

クラスパスに以下のjarファイルを設定します。

・aopalliance.jar
・guice-3.0.jar
・guice-assistedinject-3.0.jar
・guice-multibindings-3.0.jar
・guice-persist-3.0.jar
・guice-servlet-3.0.jar
・javax.inject.jar

準備はここまで


・一番簡単な例

まずは、インターフェイスを作ります

HelloService.java
----------------------------------------
public interface HelloService {

    public void execute();

}
----------------------------------------

インターフェイスを実装したクラスを作成

HelloServiceImple.java
----------------------------------------
public class HelloServiceImple implements HelloService {

    @Override
    public void execute() {
        System.out.println("Hello World");
    }
}
----------------------------------------

インターフェイスと実装クラスを紐付けるマッピングクラスを作成します

MyModule.java
----------------------------------------
import com.google.inject.AbstractModule;

public class MyModule  extends AbstractModule {

    @Override
    protected void configure() {
        bind(HelloService.class).to(HelloServiceImple.class);
    }
}
----------------------------------------
AbstractModule クラスを継承し、configure()をオーバーライドします。

bind(HelloService.class).to(HelloServiceImple.class);
ここでインターフェイスとインターフェイスを実装したクラスを紐付けます。


HelloServiceインターフェイスをインジェクトするクラスを作成します

Hello.java
----------------------------------------
import com.google.inject.Inject;

public class Hello {

    @Inject
    private HelloService service;

    public void execute(){
        service.execute();
    }
}
----------------------------------------
インジェクトする箇所に@Injectアノテーションをつけます。
で、このクラスはGuiceでインスタンスを生成します。


Hello.javaを実際に動かすクラス

MyMain.java
----------------------------------------
import com.google.inject.Guice;
import com.google.inject.Injector;

public class MyMain {

    public static void main(String[] args) {

        MyModule module = new MyModule();

        Injector injector = Guice.createInjector(module);
        Hello hello = injector.getInstance(Hello.class);
        hello.execute();


    }
}
----------------------------------------
赤文字部分の説明

Helloクラスのインスタンスを作成するために
"Injector injector = Guice.createInjector(module);"
でインジェクターを生成し、
インジェクターから
"Hello hello = injector.getInstance(Hello.class);"
でインスタンスを生成しています。

Guice.createInjector(module)引数には
作成したMyModule のインスタンスを指定します。

※Helloクラスのインスタンスをnewで作成し実行するとエラーになります。
また、@Injectをつけなかった場合もエラーになります。


実行結果
----------------------------------------
Hello World
----------------------------------------

Helloクラスで@Injectをフィールドに指定しましたが、
メソッド、コンストラクタに指定することも可能です

コンストラクタ指定の場合(Helloクラス)
----------------------------------------
    private HelloService service;

    @Inject
    public Hello(HelloService service) {
        super();
        this.service = service;
    }
----------------------------------------


メソッド指定の場合
----------------------------------------
    private HelloService service;

    @Inject
    public void setService(HelloService service) {
        this.service = service;
    }
----------------------------------------

実行結果はどれも同じです



・@Injectが複数ある場合

以下のように複数ある場合
----------------------------------------
    @Inject
    private HelloService service;

    @Inject
    private MorningService mservice;

----------------------------------------

マッピングクラスに以下のように指定します
----------------------------------------
    @Override
    protected void configure() {
        bind(HelloService.class).to(HelloServiceImple.class);
        bind(MorningService.class).to(MorningServiceImple.class);

----------------------------------------
オーバーライドしたconfigure()メソッドに
インジェクトの数だけbindを指定します。(上記の場合2つ)
(MorningServiceImpleはMorningServiceを実装したクラス)



・コンストラクタを指定する場合
インターフェイスを実装したクラスに複数コンストラクタが存在し、
コンストラクタを指定する場合
----------------------------------------
    private String message = "";

    public SomeConstractaImple(){
        this.message = "no Message";
    }


    public SomeConstractaImple(String message){
        this.message = message;

    }
----------------------------------------
青文字のコンストラクタを指定する場合は上記の方法と同じです
赤文字のコンストラクタを指定する場合は以下のようにマッピングクラスを実装します
----------------------------------------
    protected void configure() {
        bind(String.class).toInstance("HelloWorld");
        try {
            bind(SomeConstracta.class).toConstructor(SomeConstractaImple.class.getConstructor(
                    String.class));

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
----------------------------------------
オーバーライドしたconfigure()メソッドで
引数のインスタンスをbindします。

bind(SomeConstracta.class).toConstructor(SomeConstractaImple.class.getConstructor(String.class));
.toConstractorメソッドでコンストラクタを指定します。
引数は指定するコンストラクタです。
SomeConstractaImple.class.getConstructor(String.class)
は、SomeConstractaImpleクラスのストリングが引数となるコンストラクタのことです
(SomeConstractaImple(String message)のこと)


例外が発生するのでtry-catchでくくります。



・インターセプター

インターセプター用のクラスを作成します

MyInterceptor .class
----------------------------------------
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("実行前");
        Object result = invocation.proceed(); // 本来の処理
        System.out.println("実行後");

        return result;
    }
}
----------------------------------------
MethodInterceptorを実装したクラスを作成します。
本来の処理を実行する前後に処理を追加します。

マッピングクラスを以下のように実装します

InterceptorModule .class
----------------------------------------
import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;

public class InterceptorModule extends AbstractModule{

    @Override
    protected void configure() {

         bind(HelloService.class).to(HelloServiceImple.class);
         bindInterceptor(Matchers.subclassesOf(HelloService.class), Matchers.any(), new MyInterceptor());
    }
}
----------------------------------------
bindInterceptor(Matchers.subclassesOf(HelloService.class), Matchers.any(), new MyInterceptor());
ここにインターセプターを指定します。

第一引数は、クラスのマッチング条件を指定
第二引数は、メソッドのマッチング条件を指定
第三引数は、具体的なインターセプターのインスタンス、MethodInterceptorを実装したクラスを指定します。
(ここではMyInterceptor()を指定)

Matchers.subclassesOf()は特定のクラスおよびそのサブクラスを意味します。
Matchers.any()はすべてを意味します。

なので、
bindInterceptor(Matchers.subclassesOf(HelloService.class), Matchers.any(), new MyInterceptor());
は"HelloService"クラスおよびそのサブクラス、すべてのメソッドに"MyInterceptor()"のインターセプターを適用する
という意味です。


実行クラスは以下の通り

MyMain.class
----------------------------------------
import com.google.inject.Guice;
import com.google.inject.Injector;

public class MyMain {

    public static void main(String[] args) {

        InterceptorModule module = new InterceptorModule();
        Injector injector = Guice.createInjector(module);

        Hello hello = injector.getInstance(Hello.class);
        hello.execute();
    }
}
----------------------------------------
※Helloクラス、HelloServiceクラス、HelloServiceImpleクラスは上記にある実装のまま何も手を加えません。

実行結果
----------------------------------------
実行前
Hello World
実行後
----------------------------------------

マッチングは以下のようなものがあります

特定パッケージ内のクラス
Matchers.inPackage(ClassName.class.getPackage())

特定のクラスおよびサブクラス
Matchers.subclassesOf(ClassName.class)

また、自分でマッチングする条件を作成することも出来ます


クラスの場合
----------------------------------------
import com.google.inject.matcher.AbstractMatcher;

public class MyMatcherClass extends AbstractMatcher<Class<?>> {

    @Override
    public boolean matches(Class<?> clazz) {
        return clazz.getSimpleName().endsWith("Impl");
    }
}
----------------------------------------
クラス名が"Impl"で終わるクラスを指定します


メソッドの場合
----------------------------------------
import java.lang.reflect.Method;
import com.google.inject.matcher.AbstractMatcher;

public class MyMatcherMethod extends AbstractMatcher<Method> {

    @Override
    public boolean matches(Method me) {
        return me.getName().equals("display");
    }

}
----------------------------------------
メソッド名"display"が一致するメソッドを指定します

自作のマッチングクラスを使用する場合、マッピングクラスは以下のように実装します

----------------------------------------
bindInterceptor(new MyMatcherClass(), new MyMatcherMethod(), new MyInterceptor());
----------------------------------------
第一引数、第二引数に自作のマッチングクラスのインスタンスを渡すだけです


といったところですかね。

なお、当記事を書くに当たり以下のサイトを参考とさせていただきました。

Google Guice 使い方メモ
山本大@クロノスの日記
あるまに

JUGEMテーマ:Java
| JAVAとか | 14:56 | comments(0) | trackbacks(0) | pookmark |
<< 似ていると思ったのは私だけでしょうか? | main | 今更だが2ちゃんねる騒動 >>
コメント
コメントする









この記事のトラックバックURL
トラックバック機能は終了しました。
トラックバック