Guice @提供方法与提供者类 [英] Guice @Provides Methods vs Provider Classes

查看:117
本文介绍了Guice @提供方法与提供者类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开展一个相当大的项目,有很多注射。我们目前正在使用一个实现 Provider 的类,每个注入需要一个注册,而且它们主要有一行 get 方法。



每当我需要一个新的提供者时,开始创建一个新的类。在我的模块中反过来使用提供者类超过 @Provides 方法有什么好处吗? p>

解决方案

据我所知,他们完全等同于大多数简单的案例。

  / ** 
*类风格的提供者。
*在模块中:bind(Foo.class).annotatedWith(Quux.class).toProvider(MyProvider.class);
* /
class MyProvider实现Provider&Foo> {
@Inject Dep dep; //各种注入工作,包括构造器注入。

@Override public Foo get(){
return dep.provisionFoo(bar,baz);
}
}

/ **
*方法式提供者。 configure()可以是空的,但不一定是。
* /
class MyModule extends AbstractModule {
/ **名称无关紧要。 Dep自动注入* /
@Provides @Quux public Foo createFoo(Dep dep){
return dep.provisionFoo(bar,baz);
}

@Override public void configure(){/ *这里没有必要* /}
}

在任何一种风格中,Guice允许您注入 Foo Provider&Foo> ,即使该键绑定到一个类或实例。如果直接获取实例,Guice会自动调用 get ,如果不存在,则创建一个隐含的 Provider&Foo> 。绑定注释以两种样式工作。



@Provides的主要优点是紧凑,特别是与匿名内部提供者实现相比。但是请注意,您可能需要几种情况来支持Provider类:




  • 您可以创建自己的长期提供者实例,可能有构造函数参数,并将键绑定到这些实例,而不是类文字。

      bind Foo.class).toProvider(new FooProvisioner(bar,baz)); 


  • 如果您使用的是与JSR 330(javax.inject)兼容的框架,可以轻松地绑定到javax.inject.Provider类或实例。 com.google.inject.Provider扩展了该接口。

      bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class); 


  • 您的提供商可能很复杂,无法考虑到自己的课程。根据您的测试结构,以这种方式测试您的供应商可能会更容易。


  • 提供商可以扩展抽象类。使用@Provides方法可能并不容易或直观。


  • 您可以直接将多个键绑定到同一个Provider。每个@Provides方法只会生成一个绑定,尽管您可以将其他键绑定到(@Quux Foo),并让Guice执行第二次查找。


  • 如果您想(例如)缓存或记录实例而不使用Guice范围或绑定,则提供商很容易进行装饰或包装。

      bind(Foo.class).toProvider(new Cache(new FooProvisioner(bar,baz))); 







重要:虽然这是Guice无法创建的类的一个很好的策略,但请记住,Guice可以自动创建并注入 Provider< T> 对于您绑定的任何T,包括到类名,密钥或实例。不需要创建一个明确的提供者,除非你自己涉及到实际的逻辑。


I'm working on a fairly large project that has a lot of injections. We're currently using a class that implements Provider for each injection that needs one, and they mostly have one line get methods.

It's starting to get annoying to create a new class every time I need a new provider. Is there any benefit to using provider classes over @Provides methods in my Module or vice-a-versa?

解决方案

As far as I know, they're exactly equivalent for most simple cases.

/**
 * Class-style provider.
 * In module: bind(Foo.class).annotatedWith(Quux.class).toProvider(MyProvider.class);
 */
class MyProvider implements Provider<Foo> {
  @Inject Dep dep;  // All sorts of injection work, including constructor injection.

  @Override public Foo get() {
    return dep.provisionFoo("bar", "baz");
  }
}

/**
 * Method-style provider. configure() can be empty, but doesn't have to be.
 */
class MyModule extends AbstractModule {
  /** Name doesn't matter. Dep is injected automatically. */
  @Provides @Quux public Foo createFoo(Dep dep) {
    return dep.provisionFoo("bar", "baz");
  }

  @Override public void configure() { /* nothing needed in here */ }
}

In either style, Guice lets you inject Foo and Provider<Foo>, even if the key is bound to a class or instance. Guice automatically calls get if getting an instance directly and creates an implicit Provider<Foo> if one doesn't exist. Binding annotations work in both styles.

The main advantage of @Provides is compactness, especially in comparison to anonymous inner Provider implementations. Note, however, that there might be a few cases where you'd want to favor Provider classes:

  • You can create your own long-lived Provider instances, possibly with constructor parameters, and bind keys to those instances instead of to class literals.

    bind(Foo.class).toProvider(new FooProvisioner("bar", "baz"));
    

  • If you're using a framework compatible with JSR 330 (javax.inject), you can easily bind to javax.inject.Provider classes or instances. com.google.inject.Provider extends that interface.

    bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class);
    

  • Your Provider may be complex enough to factor into its own class. Depending on how you've structured your tests, it may be easier to test your Provider this way.

  • Providers can extend abstract classes. It may not be easy or intuitive to do this with @Provides methods.

  • You can bind several keys to the same Provider directly. Each @Provides method produces exactly one binding, though you could bind other keys to the key (@Quux Foo here) and let Guice do a second lookup.

  • Providers are easy to decorate or wrap, if you wanted to (for instance) cache or memoize instances without using Guice scopes or bindings.

    bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));
    


IMPORTANT: Though this is a good strategy for classes that Guice can't create, bear in mind that Guice can automatically create and inject a Provider<T> for any T that you bind in any way, including to a class name, key, or instance. No need to create an explicit provider unless there's actual logic of your own involved.

这篇关于Guice @提供方法与提供者类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆