[英]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.