Google Guice依存性注入の例チュートリアル

Google Guiceは、アプリケーションにおける依存関係の自動化フレームワークです。直接ここに来た場合、依存性注入の例をチェックすることをお勧めします。そこでは、従来のオブジェクト作成アプローチの問題と依存性注入の実装利点を学びました。前回のチュートリアルでは、アプリケーションで依存性注入を手動で実装する方法を学びました。しかし、アプリケーション内のクラスの数が増えると、このタスクを自動化するためのフレームワークを探すのが良いでしょう。Google Guiceは、依存性注入の自動実装を提供する主要なフレームワークの1つです。前の投稿から同じ例を使用して、Google Guiceを使用して依存性注入の実装プロセスを自動化する方法を学びます。Google Guiceの依存関係は、メイブンセントラルで利用可能ですので、メイブンプロジェクトの場合は以下の依存関係を追加することができます。

<dependency>
	<groupId>com.google.inject</groupId>
	<artifactId>guice</artifactId>
	<version>3.0</version>
</dependency>

単純なJavaアプリケーションをお持ちの場合は、Google Guiceホームページからjarファイルをダウンロードできます。ただし、この場合はトランジティブ依存関係もクラスパスに含める必要があります。そうでないと、実行時例外が発生します。私の例では、以下の画像のようなプロジェクト構造を持つメイブンプロジェクトがあります。それでは、各コンポーネントを1つずつ見てみましょう。

サービスクラス

package com.journaldev.di.services;

public interface MessageService {

	boolean sendMessage(String msg, String receipient);
}

MessageService インターフェースは、サービスの基本的な契約を提供します。

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class EmailService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//some fancy code to send email
		System.out.println("Email Message sent to "+receipient+" with message="+msg);
		return true;
	}

}

EmailServiceMessageService の実装の一つです。クラスが @Singleton アノテーションで注釈付けされていることに注意してください。サービスオブジェクトはインジェクタクラスを介して作成されるため、この注釈は、サービスクラスがシングルトンオブジェクトであることを知らせるために提供されています。Google Guice 3.0 では JSR-330 のサポートが追加され、com.google.injectjavax.inject パッケージのアノテーションを使用できます。Facebook メッセージを送信する別のサービス実装があるとしましょう。

package com.journaldev.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class FacebookService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//some complex code to send Facebook message
		System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
		return true;
	}

}

コンシューマクラス

アプリケーションで依存性注入を実装しているため、アプリケーション内でサービスクラスを初期化しません。Google Guice は setter-basedconstructor-based の両方の依存性注入をサポートしています。サービスを消費するアプリケーションクラスは以下のようになります。

package com.journaldev.di.consumer;

import javax.inject.Inject;

//import com.google.inject.Inject;
import com.journaldev.di.services.MessageService;

public class MyApplication {

	private MessageService service;
	
//コンストラクタベースのインジェクター
//	@Inject
//	public MyApplication(MessageService svc){
//		this.service=svc;
//	}
	
	//セッターメソッドインジェクター
	@Inject
	public void setService(MessageService svc){
		this.service=svc;
	}
	
	public boolean sendMessage(String msg, String rec){
		//ここにいくつかのビジネスロジックがあります
		return service.sendMessage(msg, rec);
	}
}

コンストラクタベースのインジェクション用のコードをコメントアウトしていることに注意してください。これは、アプリケーションがサービスクラスオブジェクトを必要としない他の機能も提供する場合に便利です。また、@Injector注釈にも注意してください。これは、Google Guiceによってサービス実装クラスがインジェクトされます。注釈に慣れていない場合は、java注釈チュートリアルを確認してください。

サービス実装のバインディング

明らかに、Google Guiceはどのサービスを使用するかわからないため、AbstractModule 抽象クラスを拡張してconfigure()メソッドの実装を提供する必要があります。

package com.journaldev.di.injector;

import com.google.inject.AbstractModule;
import com.journaldev.di.services.EmailService;
import com.journaldev.di.services.FacebookService;
import com.journaldev.di.services.MessageService;

public class AppInjector extends AbstractModule {

	@Override
	protected void configure() {
		//サービスを実装クラスにバインドする
		//bind(MessageService.class).to(EmailService.class);
		
		//MessageServiceをFacebookメッセージの実装にバインド
		bind(MessageService.class).to(FacebookService.class);
		
	}

}

私たちは実装をサービスクラスにバインドすることができることがわかります。例えば、EmailServiceに変更したい場合は、バインディングを変更するだけで済みます。

クライアントアプリケーション

セットアップは完了しましたので、簡単なJavaクラスと一緒に使い方を見てみましょう。

package com.journaldev.di.test;

import com.google.inject.Guice;
import com.google.inject.Injector;

import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.injector.AppInjector;

public class ClientApplication {

	public static void main(String[] args) {
		Injector injector = Guice.createInjector(new AppInjector());		
		
		MyApplication app = injector.getInstance(MyApplication.class);
		
		app.sendMessage("Hi Pankaj", "[email protected]");
	}

}

実装は非常に簡単です。GuiceクラスのcreateInjector()メソッドを使用してInjectorオブジェクトを作成し、インジェクタクラスの実装オブジェクトを渡します。その後、インジェクタを使用してコンシューマクラスを初期化します。上記のクラスを実行すると、以下の出力が生成されます。

Message sent to Facebook user [email protected] with message=Hi Pankaj

もしAppInjectorクラスでバインディングをEmailServiceに変更した場合、以下の出力が生成されます。

Email Message sent to [email protected] with message=Hi Pankaj

JUnitテストケース

MyApplicationクラスをテストしたいので、実際のサービス実装を作成する必要はありません。以下のような簡単なモックサービス実装クラスを使用できます。

package com.journaldev.di.services;

public class MockMessageService implements MessageService{

	public boolean sendMessage(String msg, String receipient) {
		return true;
	}

}

JUnit 4のテストクラスは以下のようになります。

package com.journaldev.di.test;


import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.services.MessageService;
import com.journaldev.di.services.MockMessageService;

public class MyApplicationTest {

	private Injector injector;
	
	@Before
	public void setUp() throws Exception {
		injector = Guice.createInjector(new AbstractModule() {
			
			@Override
			protected void configure() {
				bind(MessageService.class).to(MockMessageService.class);
			}
		});
	}

	@After
	public void tearDown() throws Exception {
		injector = null;
	}

	@Test
	public void test() {
		MyApplication appTest = injector.getInstance(MyApplication.class);
		Assert.assertEquals(true, appTest.sendMessage("Hi Pankaj", "[email protected]"));;
	}

}

お知らせしますが、私はMockMessageServiceクラスをMessageServiceAbstractModule匿名クラス実装を使用してバインドしています。これはテストメソッドの前に実行されるsetUp()メソッドで行われています。

Google Guiceプロジェクトのダウンロード

これでGoogle Guiceの例のチュートリアルは終わりです。アプリケーションで依存性の注入を実装するためのGoogle Guiceの使用は非常に簡単で、美しく行います。GoogleのAPIでも使用されているため、高いテストと信頼性が期待できます。上記からプロジェクトをダウンロードして詳細を学習してください。

Source:
https://www.digitalocean.com/community/tutorials/google-guice-dependency-injection-example-tutorial