[英]Guice injection with Builder pattern for client lib
我是Google Guice的新手,我正試圖將我的頭腦用於我的特定場景。 我正在構建一個非常復雜的服務客戶端,並且(我相信)確實需要正確地實例化Builder模式。 因為這個客戶端最終會被打包到自己的JAR庫中,所以我希望Guice能夠處理它的DI。 以下是我的代碼的大大簡化版本:
public interface MyClient {
public FizzResource getFizzResource();
public BuzzResource getBuzzResource();
public FooResource getFooResource();
}
public class MyClientImpl implements MyClient {
// See below
}
public class GetFizzCommand {
// omitted for brevity
}
public class GetBuzzCommand {
// omitted for brevity
}
public class GetFooCommand {
// omitted for brevity
}
public interface FizzResource {
Fizz getFizz(Long fizzId);
}
public class FizzResourceImpl implements FizzResource {
private GetFizzCommand getFizzCommand;
@Override
Fizz getFizz(Long fizzId) {
return getFizzCommand.doGetFizz(fizzId);
}
}
public interface BuzzResource {
Buzz getBuzz(Long buzzId);
}
public class BuzzResourceImpl implements BuzzResource {
private GetBuzzCommand getBuzzCommand;
@Override
Buzz getBuzz(Long buzzId) {
return getBuzzCommand.doGetBuzz(buzzId);
}
}
public interface FooResource {
Foo getFoo(Long fooId);
}
public class FooResourceImpl implements FooResource {
private GetFooCommand getFooCommand;
@Override
Foo getFoo(Long fooId) {
return getFooCommand.doGetFoo(fooId);
}
}
因此,您可以看到層次結構/ dep圖如下:
MyClient
應注入*ResourceImpl
*ResourceImpl
都應該注入一個*Command
實例 預期的用例是使構建MyClient
impl變得如此簡單:
MyClient myClient = MyClientImpl.Builder("myservice.example.org", 8080L, getWidget())
.withAuth("user", "password")
.withHttps()
.withFailureStrategy(someFailureStrategy)
// ...etc.
.build();
所以這是我對MyClientImpl
,其內部構建器和我的Guice模塊的最佳嘗試:
public class BaseClient {
private String uri;
private long port;
private Widget widget;
// ctor, getters and setters
}
public class MyClientImpl extends BaseClient implements MyClient {
@Inject
private FizzResource fizzResource;
@Inject
private BuzzResource buzzResource;
@Inject
private FooResource fooResource
public MyClientImpl(String uri, long port, Widget widget) {
super(uri, port, widget);
}
public static class Builder {
private String uri;
private long port;
private Widget widget;
Builder(String uri, long port, Widget widget) {
super();
setUri(uri);
setPort(port);
setWidget(widget);
}
// Lots of methods on the builder setting lots of MyClient-specific properties
// that I have omitted here for brevity.
MyClient build() {
Injector injector = Guice.createInjector(new MyClientModule(this));
return injector.getInstance(MyClient.class);
}
}
}
public class MyClientModule extends AbstractModule {
private MyClientImpl.Builder builder;
public MyClientModule(MyClientImpl.Builder builder) {
super();
setBuilder(builder);
}
@Override
protected void configure() {
MyClientImpl myClientImpl = new MyClientImpl(builder.getUri(), builder.getPort(), builder.getWidget());
bind(MyClient.class).toInstance(myClientImpl);
}
}
但對於我的生活,我看不出如何/在哪里:
*Command
s綁定到*ResourceImpl
; 和 *ResourceImpl
綁定到MyClientImpl
實例 有任何想法嗎?
目前還不清楚你注射的是什么。 您可能會因為關於構建器和設計的其他方面而進一步混淆此事。 我建議你將代碼剝離到一個功能但不包含任何注入的SSCCE ,然后通過注入一個字段來增加你的設計。 現在你所有的代碼展示都是復雜設計的修剪骨架,注入沒有意義,沒有辦法運行代碼,看看會發生什么。 Guice在運行時運行,因此我們必須看到您的main
方法,以查看應用程序代碼實際執行的操作。
下面是我上面描述的一個非常簡單的例子。
具有兩個不同impl的接口:
public interface Service {
void useService();
}
public class FooService implements Service {
public void useService() {
System.out.println("foo service used");
}
}
public class BarService implements Service {
public void useService() {
System.out.println("bar service used");
}
}
此接口的vanilla(非Guice)用戶:
public class ServiceUser {
Service service = new FooService(); // change impl to be used here
public static void main(String[] args) {
new ServiceUser().service.useService();
}
}
此界面的Guicified用戶:
public class ServiceUserGuicified {
@Inject
Service service;
public static void main(String[] args) {
Injector injector = Guice.createInjector(new FooServiceModule());
ServiceUserGuicified user = injector.getInstance(ServiceUserGuicified.class);
user.service.useService();
}
}
public class FooServiceModule extends AbstractModule {
@Override
protected void configure() {
bind(Service.class).to(FooService.class);
}
}
在Guicified版本中,impl定義在Guice模塊中編碼,而不是在運行時代碼中編碼。 運行時代碼包含的唯一內容是在創建注入器時使用模塊。 您可以為bar服務創建一個新模塊,並使用它來創建一個注入器,或者您可以更改主服務模塊中的綁定。
一旦你理解了上面發生的事情,你應該能夠通過重復你想要由Guice注入的每個實例的概念來解決你自己代碼中的任何問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.