Google Guice依赖注入框架完全指南:从入门到实例应用

Google Guice 依赖注入实例教程

Google Guice是一个用于自动化应用程序中依赖注入的框架。如果您直接阅读本文,建议您先查看依赖注入示例,了解传统对象创建方法的问题以及依赖注入的实施优势。在上一教程中,我们学习了如何手动实现依赖注入。但当应用程序中的类数量增多时,最好寻找一些框架来自动化这个任务。Google Guice是其中一个主要框架,其主要工作是提供依赖注入的自动实现。我们将继续使用上一篇文章中的示例,学习如何使用Google Guice自动进行依赖注入的实现过程。Google Guice的依赖项可以在Maven中央库中找到,因此对于Maven项目,您可以添加以下依赖项:

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

如果您有一个简单的Java应用程序,那么您可以从Google Guice在Google Code的主页上下载jar文件。请注意,在这种情况下,您还需要在类路径中包含其传递依赖,否则将会出现运行时异常。以我的例子为例,我有一个Maven项目,其项目结构如下图所示。让我们逐个查看每个组件。

服务接口

package com.Olivia.di.services;

public interface MessageService {

	boolean sendMessage(String msg, String receipient);
}

MessageService 接口为服务提供基础合约。

package com.Olivia.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class EmailService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//发送电子邮件的一些复杂代码
		System.out.println("邮件已发送至 "+receipient+",内容为:"+msg);
		return true;
	}

}

EmailService是MessageService的一种实现。请注意,该类已用@Singleton注解进行了标记。由于服务对象将通过注入器类创建,因此提供了此注解以让框架知道服务类应该是单例对象。Google Guice 3.0新增了对JSR-330的支持,我们可以使用com.google.inject或javax.inject包中的注解。假设我们还有另一个服务实现来发送Facebook消息:

package com.Olivia.di.services;

import javax.inject.Singleton;

//import com.google.inject.Singleton;

@Singleton
public class FacebookService implements MessageService {

	public boolean sendMessage(String msg, String receipient) {
		//发送Facebook消息的一些复杂代码
		System.out.println("Facebook消息已发送至用户 "+receipient+",内容为:"+msg);
		return true;
	}

}

消费者类

既然我们在应用程序中实施了依赖注入,因此我们不会在应用程序中直接初始化服务类。Google Guice支持基于setter和构造函数的两种依赖注入方式。我们使用服务的应用程序类如下所示:

package com.Olivia.di.consumer;

import javax.inject.Inject;

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

public class MyApplication {

	private MessageService service;
	
	//基于构造函数的注入
	// @Inject
	// public MyApplication(MessageService svc){
	// 	this.service=svc;
	// }
	
	//基于setter方法的注入
	@Inject
	public void setService(MessageService svc){
		this.service=svc;
	}
	
	public boolean sendMessage(String msg, String rec){
		//此处是一些业务逻辑
		return service.sendMessage(msg, rec);
	}
}

请注意,我对构造函数注入的代码进行了注释,当您的应用程序还提供了其他不需要服务类对象的功能时,这将非常方便。还请注意@Inject注解,这将被Google Guice用于注入服务实现类。如果您对注解不熟悉,请查看Java注解教程。

服务绑定实现

显然,Google Guice并不知道要使用哪个服务实现,我们必须通过扩展AbstractModule抽象类并为configure()方法提供实现来进行配置:

package com.Olivia.di.injector;

import com.google.inject.AbstractModule;
import com.Olivia.di.services.EmailService;
import com.Olivia.di.services.FacebookService;
import com.Olivia.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.Olivia.di.test;

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

import com.Olivia.di.consumer.MyApplication;
import com.Olivia.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("你好 Pankaj", "scdev@abc.com");
	}

}

实现非常容易理解。我们需要使用Guice类的createInjector()方法创建Injector对象,其中我们传入我们的实现了injector类的对象。然后我们使用injector来初始化我们的消费者类。如果我们运行上述类,它将产生以下输出:

Facebook消息已发送至用户 scdev@abc.com,内容为:你好 Pankaj

如果我们在AppInjector类中更改对EmailService的绑定,那么将产生以下输出结果:

邮件已发送至 scdev@abc.com,内容为:你好 Pankaj

JUnit测试用例

因为我们想要测试MyApplication类,所以我们不需要创建实际的服务实现。我们可以有一个简单的模拟服务实现类,如下所示:

package com.Olivia.di.services;

public class MockMessageService implements MessageService{

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

}

我的JUnit 4测试类如下所示:

package com.Olivia.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.Olivia.di.consumer.MyApplication;
import com.Olivia.di.services.MessageService;
import com.Olivia.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("你好 Pankaj", "scdev@abc.com"));
	}

}

请注意,我通过使用匿名类实现AbstractModule,将MockMessageService类与MessageService进行绑定。这是在运行测试方法之前的setUp()方法中完成的。

下载Google Guice项目

Google Guice示例教程就介绍到这里。在应用中使用Google Guice实现依赖注入非常简单且有效。它被用于Google的API中,因此我们可以认为它经过了高度测试,并且是可靠的代码。从上面下载该项目并进行尝试,以了解更多。

bannerAds