【问题标题】:How to create and use and instance using guice in java playjava play中如何使用guice创建和使用实例
【发布时间】:2018-05-31 11:10:28
【问题描述】:

我正在尝试使用 guice,我想在 Java Play 2.6 中创建一个单例随机 Web 服务客户端

现在我有我的 WS 客户端,它作为 java 播放模块加载。当我运行应用程序时,没问题,我的客户端能够使用注入的 java play 配置 (com.typesafe.config.Config)。但是,如果我尝试在其他任何地方使用我的客户端,我会收到一条错误消息:No implementation for com.typesafe.config.Config was bound。

这是我的(非常简单的)客户:

import play.Logger;
import com.typesafe.config.Config;

@Singleton
public class MyClient {
    final Config config;

    @Inject
    public MyClient(Config config) {
        this.config = config;
        Logger.warn("constructor called")
        Logger.warn("Some config param:"+config.getString("some_param"))
    }

    public void doSomething() {
        Logger.warn("doSomething() called")
    }

}

我的模块实现了 Guice 的 AbstractModule :

import com.google.inject.AbstractModule;

public class MyClientModule extends AbstractModule {
    @Override 
    protected void configure() {
        bind(MyClient.class).asEagerSingleton();
    }

}

当我告诉 Play 将其用作 applicationf.conf 中的模块时,它可以工作(我在控制台中收到 "Constructor called" 和 "Some config param" 警告日志):

play {
  modules {
    enabled += external.MyClientModule
  }
}

但如果我尝试从我的HomeController 调用它:

public class HomeController extends Controller {
    public Result index() {
        Injector myClientInjector = Guice.createInjector(new MyClientModule());
        MyClient myClient = myClientInjector.getInstance(MyClient.class);
        return ok(views.html.index.render());
    }
}

然后我收到以下错误:

[CreationException: Unable to create injector, see the following errors:

1) No implementation for com.typesafe.config.Config was bound.
  while locating com.typesafe.config.Config
    for the 1st parameter of external.MyClient.<init>(MyClient.java:121)
  at external.MyClientModule.configure(MyClientModule.java:8)

1 error]

我很确定这里有一些问题,那么绑定然后使用它的正确方法是什么?

【问题讨论】:

    标签: java dependency-injection playframework guice


    【解决方案1】:

    在 HomeController 中,使用构造函数注入:

    @Inject
    public HomeController (final MyClient myclient) {
        this.myclient = myclient;
    }
    

    您可以像这样注释 1 个构造函数,因此它需要包含您要注入的所有类。可以结合构造函数和字段注入,但不建议这样做。

    【讨论】:

    • 您好,就像我之前说的,请把关于bind(MyClient.class).in(Singleton.class)的部分去掉,这不是解决方案的一部分。它与asEagerSingleton() 配合得很好
    【解决方案2】:

    asEagerSingleton() 绑定意味着它被尽快绑定。这种情况下,Config还没有绑定,所以失败了。

    使用

    bind(MyClient.class).in(Singleton.class)
    

    在需要时将其绑定为单例。

    在 HomeController 中,使用构造函数注入:

    @Inject
    public HomeController (final MyClient myclient) {
        this.myclient = myclient;
    }
    

    您可以像这样注释 1 个构造函数,因此它需要包含您要注入的所有类。可以结合构造函数和字段注入,但不建议这样做。

    【讨论】:

    • 遗憾的是,在MyClientModule 中将bind(MyClient.class).asEagerSingleton(); 替换为bind(MyClient.class).in(Singleton.class) 时,我遇到了完全相同的问题。此外,当使用asEAcgerSingleton() 时,模块实际上是在启动时构建的(如果我记录了它确实出现在控制台中的内容,我可以读取配置中的内容)。我编辑了我的帖子以明确说明这一点。
    • 你为什么不在控制器构造函数中 @Inject MyClient ? \@Inject public HomeController(MyClient myclient) { this.myclient = myclient }
    • 您也可以将其作为字段注入,但我建议在所有情况下都使用构造函数注入。
    • 我不控制Controller构造函数的调用,它是play框架内部的。但是由于在 Controller 中调用客户端只是一个示例,我不需要在这里实际调用它,您可能只是给了我问题的答案。我会试一试,然后回来告诉我是什么。谢谢!
    • 如果你只创建1个构造函数,用@Inject注解,就可以了。即使您不控制实例化。
    猜你喜欢
    • 2015-08-19
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多