【问题标题】:How to inject the default Guice Provider into my custom Provider?如何将默认的 Guice Provider 注入我的自定义 Provider?
【发布时间】:2013-03-21 12:25:38
【问题描述】:

如果我创建一个提供程序并将其绑定到一个类,就像这样

bind(MyClass.class).toProvider(MyClassProvider.class)

然后Provider<MyClass>自动绑定to MyClassProvider。如果您想将Provider<MyClass> 注入MyClassProvider,那就会出现问题,如下所示:

@Inject
public MyClassProvider(Provider<MyClass> provider)

我想将默认的 Guice 提供程序注入到我的提供程序中,以便我可以轻松地在我的自定义提供程序中创建新实例。该怎么做?

【问题讨论】:

  • 为什么要这样做? MyClassProvider 会做 provider.get() 而不是 new MyClass() ?
  • 我想这样做是因为 MyClass 的构造函数并不是那么简单——它还有其他注入的依赖项,而这些依赖项又具有依赖项。第二个原因是实际上我正在编写一个通用提供程序,我想将它用于许多这样的实际类:bind(MyClass.class).toProvider(new TypeLiteral>() {});
  • 好的,第一个原因。这个通用提供者会做什么?可能,还有其他解决方案。
  • 通用提供者将请求的类路由到特定的缓存实例。 (路由基于 HTTP 请求中的标头,返回的实例特定于后端实例)我认为它可以使用自定义 Guice 范围以某种方式实现,但我认为它会更难。
  • 基本上如果之前已经创建过HTTP请求中指示的标签后端,我会返回之前构建的缓存实例。如果这是第一次,我会使用默认的 guice 提供者创建整个对象图。我的数据库连接提供程序当然会根据 HTTP 请求再次检查要连接的后端。我不必在每次请求时都构建整个对象图,但前提是我第一次连接到某个后端。所以我想要的是类似“命名单例”的东西。 (名称基于 http 请求)

标签: dependency-injection guice


【解决方案1】:

您需要在两者之一上使用binding annotation。如果您不介意 MyClass 的用户被注释,这很容易。

public class AccountTest {

   @Test
   public void test() {
       Injector injector = Guice.createInjector(new AbstractModule() {

           @Override
           protected void configure() {
               bind(MyClass.class).annotatedWith(Names.named("MYPROVIDER")).toProvider(MyClassProvider.class);
           }
       });
       MyClassUser user = injector.getInstance(MyClassUser.class);

       assertTrue(user.get().myProvider); // Shows if was created via my provider or the Guice provider.
   }
}

class MyClassUser {
    Provider<MyClass> provider;

    @com.google.inject.Inject
    public MyClassUser(@Named("MYPROVIDER") Provider<MyClass> provider) {
        this.provider=  provider;
    }

    MyClass get() {
        return provider.get();
    }
}

class MyClass {
    boolean myProvider = false;
}

class MyClassProvider implements Provider<MyClass> {
    Provider<MyClass> provider;

    @com.google.inject.Inject
    public MyClassProvider(Provider<MyClass> provider) {
        this.provider=  provider;
    }

    @Override
    public MyClass get() {
        MyClass c = provider.get();
        c.myProvider = true;
        return c;
    }

    public String toString() {
        return "Our provider";
    }
}

如果您不希望 MyClass 的用户使用命名提供程序,我能够让它工作的唯一方法是扩展 MyClass 并让 MyClassProvider 需要一个“MyClass2”提供程序.作为一种解决方案,它闻起来很有效(而不是用糟糕的答案污染这个答案,您可以在this gist 上找到代码)。

您可以使用私有模块或子模块来完成此操作(因为它是机器人腿问题的变体),但我一直无法弄清楚如何做到这一点。

【讨论】:

    猜你喜欢
    • 2021-10-19
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多