Google Guice 学习笔记(1) Hello Guice

本文通过一个简单的自动贩卖机示例介绍了Google Guice框架的基本使用方法。Guice是一款轻量级依赖注入框架,用于替代Java应用程序中的直接new操作,从而降低组件间的耦合度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看了一点Dependency Injection的东西, 发现很难理解为什么要使用DI, 为什么要IoC, 到底能带来什么好处. 于是决定选择一款框架学习一下, 以增进自己的理解. 比较之后, 选择了Google Guice, 主要还是从如何使用入手.


1. Guice简介

Guice是Google开发的一款轻量级的注入框架(a lightweight dependency injection framework for Java 5 and above), 与大名鼎鼎的Spring相比, 确实是轻量级的框架. 其主要目标是替代开发中使用关键字new或者大量使用的工厂方法, 以达到解除耦合的目的; 同样该框架的作者Bob Lee也希望Guice能给使用者带来更好的体验, 能帮助开发者提高开发速度和方便维护. OK, 废话不多说了. 详细的介绍可以去官网查看: http://code.google.com/p/google-guice/


2. Hello Guice

我使用的参考书为Apress的Google Guice(Agile Lightweight Dependency Injection Framework), 是Google官网Slice的推荐用书. 该书使用了一个FortuneCookie的例子, 非常形象的介绍了Guice的使用方法. 在本文, 参考介绍使用贩卖Juice的VendingMachine作为例子.


在科技发展初期, 一切都是那么简单.

我们有一个只贩卖一种果汁的自动贩卖机. 为此我们提供了一个接口, 因为世界上不止这么简单的一种贩售机, 除了果汁, 还能卖点别的东西. 而自动贩卖机的果汁也很简单, 只包含一个价格的属性, 当然果汁的味道还是不错的.

public interface VendingMachine {
    public int showPrice();
    public Juice sellJuice();
}

import java.util.Arrays;
import java.util.List;

public class VendingMachineImpl implements VendingMachine {
	
	private static final List KINDS_OF_JUICE =
		Arrays.asList(
			new Juice(100)
		);
	@Override
	public int showPrice() {
		return KINDS_OF_JUICE.get(0).getPrice();
	}
	@Override
	public Juice sellJuice() {
		return KINDS_OF_JUICE.get(0);
	}
}

public class Juice {
	private int price;
	public Juice(int price) {
		this.price = price;
	}
	public int getPrice() {
		return price;
	}
	public String toString() {
		return "It tastes good!";
	}
}



那么作为消费者Consumer, 可以询问价格并且购买果汁. 当然购买果汁需要自动贩售机提供服务.

import com.google.inject.Inject;

public class Consumer {
	private VendingMachine vendingMachine;
	
	@Inject
	public Consumer(VendingMachine vendingMachine) {
		this.vendingMachine = vendingMachine;
	}
	public int getPrice() {
		return vendingMachine.showPrice();
	}	
	public Juice buyJuice() {
		return vendingMachine.sellJuice();
	}
}


在构造函数上我们添加了一个@Inject的标记, 这个是Guice的标记, 表示在构造函数进行Inject, 再加上Module, 我们就可以把VendingMachine和VendingMachineImpl粘合起来. Module是Guice提供的一个接口, 是其指定实现方式的一种方法, 也是比较推荐的一种方式. 绑定的语法可以这么来读: 绑定VendingMachine到VendingMachineImpl的实现上, 使用单例模式. 在Module中进行绑定后, 在标记为@Inject的地方, Guice就会自动为其指定一个实现的实例.

import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.Scopes;

public class VendingMachineModule implements Module {

	@Override
	public void configure(Binder binder) {
		binder.bind(VendingMachine.class)
			  .to(VendingMachineImpl.class)
			  .in(Scopes.SINGLETON);
	}

}

 

万事俱备, 只欠东风. 接下来该喝点果汁了. 通过Guice.createInjector使用我们的Module定义创建出一个Injector后, 我们就可以通过getInstance方法来获取各种对象, 从此告别new和工厂方法. 

 

public class Bootstrap {
	public static void main(String[] args) {
		Injector injector = Guice.createInjector(new VendingMachineModule());
		Consumer consumer = injector.getInstance(Consumer.class);
		System.out.println("The price of juice is " + consumer.getPrice());
		System.out.println("So, buy this juice and drink it: " + consumer.buyJuice());
	}
}
 

以上为第一个Guice的例子, 我们可以简单的总结出最基本的使用方法: 通过Module配置抽象与实现的关系, 通过@Inject标签来标记注入点. 然后使用万能的Injector来获得对象. 应该是一个很明确的思路, 使用起来也比较简洁.

但是问题随之而来:

1. 这样做能为我们带来什么好处呢? 

2. 这就是传说中的Dependency Injection, 该如何去解释. 

3. 我们如何能提供更多的服务(More Juice).

4. 我们还有一台售卖零食的自动贩卖机, 我们如何能在买到果汁之后, 再去购买些零食呢? 

 

后面的学习将继续对Guice框架的细节进行学习, 并围绕以上问题来做一些思考.

 

 

 

 

Acai 是 JUnit4 和 Guice 的测试库,可以更容易的编写应用功能测试。主要特性:注入测试需要的助手类启动测试需要的任意的服务 运行测试之间的服务清理按照正确顺序启动多个服务 创建测试作用域绑定Acai 主要针对的是应用大型功能测试。安装<dependency>   <groupId>com.google.acai</groupId>   <artifactId>acai</artifactId>   <version>0.1</version>   <scope>test</scope> </dependency>使用 Acai 进行测试注入@RunWith(JUnit4.class) public class SimpleTest {   @Rule public Acai acai = new Acai(MyTestModule.class);   @Inject private MyClass foo;   @Test   public void checkSomethingWorks() {     // Use the injected value of foo here   }   private static class MyTestModule extends AbstractModule {     @Override protected void configure() {       bind(MyClass.class).to(MyClassImpl.class);     }   } }使用 Acai 启动服务@RunWith(JUnit4.class) public class ExampleFunctionalTest {   @Rule public Acai acai = new Acai(MyTestModule.class);   @Inject private MyServerClient serverClient;   @Test   public void checkSomethingWorks() {     // Call the running server and test some behaviour here.     // Any state will be cleared by MyFakeDatabaseWiper after each     // test case.   }   private static class MyTestModule extends AbstractModule {     @Override protected void configure() {       // Normal Guice modules which configure your       // server with in-memory versions of backends.       install(MyServerModule());       install(MyFakeDatabaseModule());       install(new TestingServiceModule() {         @Override protected void configureTestingServices() {           bindTestingService(MyServerRunner.class);           bindTestingService(MyFakeDatabaseWiper.class);         }       });     }   }   private static class MyServerRunner implements TestingService {     @Inject private MyServer myServer;     @BeforeSuite void startServer() {       myServer.start().awaitStarted();     }   }   private static class MyFakeDatabaseWiper implements TestingService {     @Inject private MyFakeDatabse myFakeDatabase;     @AfterTest void wipeDatabase() {       myFakeDatabase.wipe();     }   } } 标签:Acai
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值