Google Guice入门示例

  |   0 评论   |   2,298 浏览

Google Guice是一个依赖注入(DI)框架,实现了控制反转(IOC)。


优点:比spring轻,被越来越多的开源工具使用

缺点:调用时出现异常时,Guice不会抛出异常。需要开发者自己解决。


本文用一个示例,来说明这种调用。


背景

在数据流的处理中,会用到生产者消费者模型,如通过http服务接收到日志数据,然后经过业务处理,最终存储到本地磁盘中。

随着业务变化,数据生产者会变化,如不再通过http接收数据,而是通过从消息队列中读取数据。数据消费者也会变化,如不再存储到本地磁盘,而是存储到远程的Hadoop中。

在这个过程中,业务处理逻辑是不变的,我们也希望能够复用业务代码逻辑,同时可以选用合适的生产和消费实现。


传统实现

那么怎么做呢?一般会写三个接口文件:生产者,消费者,业务处理者,如下:


// 业务处理接口


public interface GatewayService {

	void start();

	void stop();
}
// 生产者接口
public interface ProduceService {

	List<String> getDataList();

	void start();

	void stop();
}



// 消费者接口
public interface ConsumeService {

	void consume(List<String> dataList);
}


然后分别实现:





// 业务处理实现类
public class GatewayServiceImpl implements GatewayService {

	private ConsumeService consumer;

	private ProduceService producer;

	private volatile boolean isRunning = false;

	public GatewayServiceImpl(ProduceService producer, ConsumeService consumer) {
		this.producer = producer;
		this.consumer = consumer;
	}

	public void start() {
		if (isRunning) {
			throw new IllegalStateException("already running");
		}

		new Thread(new Runnable() {
			public void run() {
				try {
					isRunning = true;
					while (isRunning) {
						List<String> dataList = producer.getDataList();
						consumer.consume(dataList);
					}
				} finally {
					isRunning = false;
				}
			}
		}, "gateway-service").start();
	}

	public void stop() {
		this.isRunning = false;
	}
}

// 生产者基类



public abstract class AbstractProducerService implements ProduceService {

	public void start() {
	}

	public void stop() {
	}

}



// 生产类实现类
public class MockProducer extends AbstractProducerService implements ProduceService {

	private static AtomicLong counter = new AtomicLong(0);

	public List<String> getDataList() {
		try {
			Thread.sleep(500L);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return Collections.singletonList(String.valueOf(counter.incrementAndGet()));
	}

}
// 消费者实现类
public class MockConsumer implements ConsumeService {

	public void consume(List<String> dataList) {
		System.out.println("MockConsumer: " + dataList);
	}
}


最后把代码组装起来





	public static void main(String[] args) throws InterruptedException {
		ProduceService producer = new MockProducer();
		ConsumeService consumer = new MockConsumer();
		GatewayService service = new GatewayServiceImpl(producer, consumer);
		service.start();
		Thread.sleep(10000L);
		service.stop();
	}



这是一般的写法


Guice实现

如果采用Guice的话,将new 新的实例的过程,由guice来接管。



public class MockGatewayModule implements Module {

	public void configure(Binder binder) {
		binder.bind(ConsumeService.class).to(MockConsumer.class);
		binder.bind(ProduceService.class).to(MockProducer.class);
		binder.bind(GatewayService.class).to(GatewayServiceImpl.class).asEagerSingleton();
	}

}


然后将GatewayService接口的初始化中参数的传入,由注入来实现,下面的代码中,增加了一个 @Inject注解


public class GatewayServiceImpl implements GatewayService {

	private ConsumeService consumer;

	private ProduceService producer;

	private volatile boolean isRunning = false;

	@Inject
	public GatewayServiceImpl(ProduceService producer, ConsumeService consumer) {
		this.producer = producer;
		this.consumer = consumer;
	}

	public void start() {
		if (isRunning) {
			throw new IllegalStateException("already running");
		}

		new Thread(new Runnable() {
			public void run() {
				try {
					isRunning = true;
					while (isRunning) {
						List<String> dataList = producer.getDataList();
						consumer.consume(dataList);
					}
				} finally {
					isRunning = false;
				}
			}
		}, "gateway-service").start();
	}

	public void stop() {
		this.isRunning = false;
	}
}




最近新的代码组装方式:


	public static void main(String[] args) throws InterruptedException {
		Injector injector = Guice.createInjector(new MockGatewayModule());
		injector.getInstance(GatewayService.class).start();
		Thread.sleep(10000L);
		injector.getInstance(GatewayService.class).stop();
	}

结果

执行效果是相同的,但是有下面的两个特点:


  1. 接口实例的产生放在了Module中来进行,省去了new的过程
  2. 通过注入,避免了实例中参数的显式传入



进一步阅读:







评论

发表评论

validate