当前位置: 首页 > 知识库问答 >
问题:

使用guice进行客户端sdk/库设计模式的依赖注入

吴涵育
2023-03-14

我正在为web API构建客户端SDK,并尝试通过guice应用依赖注入。第三方将使用此Java客户端作为访问我们API的一种方式。

我希望能够注入我的外部依赖项(使用的HTTP客户端等),并为开发人员提供一种方法来注入这些依赖项的不同版本,如果他们愿意,或者如果我想自己更改实现(依赖项注入的一个好例子,对吗?)。

但是,为了连接依赖项,我必须让我的库的用户创建一个注入器等,类似这样:

Injector injector = Guice.createInjector(new MyAPIClientModule(url, username, password));
        this.service = injector.getInstance(MyAPIService.class);

我不想将其推给我的库的用户,但我仍然希望让用户能够选择不同的实现或底层HTTP库等。

不知怎么的,我是不是没抓住要点?这是使用guice时的标准做法吗?

或者我应该将它包装在另一个执行注入的类中,并向第三方用户提供一个简单的Java对象

共有2个答案

南门宇
2023-03-14
    < li >您可以html" target="_blank">执行生产中不建议的模块覆盖。您可以在这里找到更多关于在Guice中重写绑定的内容 < ol start="2 " > < li >您可以使用< code>@ImplementedBy创建绑定,但接口的显式绑定将覆盖该批注绑定。因此,如果可能的话,您将使用< code>@ImplementeBy创建您的框架,并且第三方开发人员将在他们的模块中使用显式绑定来覆盖它。查找更多https://code . Google . com/p/Google-guice/wiki/JustInTimeBindings < li >总之,这些方法我都不熟悉。我建议创建一个抽象的< code>ApiClient,让第三方开发者来实现开放点。也许您应该引入一些< code >注释,比如必须实现< code>ClientApi的< code>@Client。然后,您的模块将在类路径中搜索带有< code>@Client批注的< code>ClientApi的实现。假设注释将包含一个值< code > @ Client(' Apache-http '),您将引入一个配置属性' api-client ',对于默认实现,该属性将被设置为< code>default,如果您想使用不同的内容,则可以设置为< code>apache-http。你应该考虑一下,因为错误的绑定很容易破坏你的ApiClient的完整性:)。
燕靖
2023-03-14

我希望能够注入我的外部依赖项(http客户端使用的等等),并为开发人员提供一种方法,如果他们想或者如果我想自己更改实现的话,可以注入这些依赖项的不同版本(这是一个很好的依赖项注入案例,对吗?)。

对于DI来说,这是一个很好的案例,这是很有争议的。像HTTP客户端这样的外部依赖通常有具体的接口,除了依赖之外没有人实现它。就我个人而言,我无法想象你的程序是如何编写的,因为交换底层HTTP客户端不会影响它的架构,也就是说,除非你为它提供自己的外观,比如

public interface HttpClient {
    HttpResponse send(HttpRequest request);
}

其中Http请求Http响应也是自定义类/接口。但是向最终用户提供这种扩展点很少合适,尤其是如果您没有一些参考实现(这意味着用户必须为他/她想要的依赖项创建这个外观)。这在极少数情况下是合适的,但很可能这不是您的情况。

同一依赖项的不同版本通常也不适用于DI,因为交换版本可以在构建/组装时完成。

如果您想为用户提供一些库“移动部件”的自己实现的能力,那么首先您必须为所有这些移动部件定义严格的接口。换句话说,提供一组接口,您的用户必须扩展这些接口,并将其注入您的类中。

然后创建由Guice模块组成的“绑定空间”,并在这些模块中声明这些接口的要求:

public class SomeModule extends AbstractModule {
    @Override
    protected void configure() {
        requireBinding(SomeUserAPI.class);
        // Other bindings which probably use SomeUserAPI in implementations
    }
}

通过声明所需的绑定,您可以确保没有人能够在您的模块中混合,除非他们提供给定类的一些实现。当然,如果找不到绑定,Guice 无论如何都会失败,但是当您明确要求它时,您将获得更具体的错误消息,以及模块的清晰接口。

然后,您为库创建特殊的“入口点”,其唯一责任是创建注入器并为用户提供类的实例。此类接受来自用户的 Guice 模块并将其集成到注入器中。

public class Library {
    private final Injector injector;

    private Library(Module userModule) {
        // SomeModule and AnotherModule are modules defined in the library
        // and they are not the part of public interface of your library
        this.injector = Guice.createInjector(userModule, new SomeModule(), new AnotherModule());
    }

    public static Library create(Module userModule) {
        return new Library(userModule);
    }

    public MyAPIService myAPIService() {
        return injector.getInstance(MyAPIService.class);
    }
}

然后用户这样使用它:

Library library = Library.create(new AbstractModule() {
    @Override
    protected void configure() {
        // recall requireBinding(SomeUserAPI.class) statement we wrote previously,
        // here we are "implementing" it
        bind(SomeUserAPI.class).to(SomeUserAPIImpl.class);
        // other bindings for your exposed interfaces
    }
});
MyAPIService service = library.myAPIService();

在这种方法中,您允许用户使用Guice DI以简洁且受控的方式扩展您的库。

但是,您仍然必须向用户公开Guice(因为用户必须实现模块接口)。我不认为你可以完全避免这种情况,除非你做一些奇怪的事情,比如

Library.create(SomeUserAPIImpl.class, SomeUserAPI2Impl.class, ...)

也就是说,接受表示扩展点实现的类对象(然后将它们绑定在某个内部模块中)。但是我不认为从库接口中消除Guice真的值得。

 类似资料:
  • 问题在于Azure WebJobs SDK只支持公共静态方法作为作业入口点,这意味着无法实现构造函数/属性注入。 我在官方WebJobs SDK文档/资源中找不到有关此主题的任何内容。我遇到的唯一解决方案是基于本文描述的服务定位器(anti)模式。 对于基于Azure WebJobs SDK的项目,有没有一种好方法可以使用“适当的”依赖项注入?

  • 问题内容: 我的团队正在研究依赖项注入框架,并试图在使用Google-Guice和PicoContainer之间做出选择。 我们正在寻找框架中的几件事情: 较小的代码占用空间-我的意思是较小的代码占用空间是我们不想在我们的代码库中到处都有依赖项注入代码垃圾。如果我们需要在将来进行重构,我们希望它尽可能简单。 性能-创建和注入对象时,每个框架有多少开销? 易于使用-学习曲线是否很大?我们是否必须编写

  • 例如,Foos的资源可能如下所示: 对于酒吧:

  • 从零开始,没有任何以前的Jersey 1.x知识,我很难理解如何在我的Jersey 2.0项目中设置依赖注入。 我也知道HK2在Jersey 2.0中可用,但我似乎找不到有助于Jersey 2.0集成的文档。 我可以让容器启动并提供我的资源,但是当我将@inject添加到MyService时,框架就会抛出一个异常: 我的starter项目可在github:https://github.com/do

  • 我尝试在我的活动中注入修改,但我得到了空异常 这是AndroidApplication类

  • 我想在使用guice实例化子类时,将依赖项注入父类。在下面的示例中,我试图创建的一个实例,同时希望能够在运行时使用Guice注入。我该怎么做?