Guice配置范围

时间:2016-08-10 18:59:45

标签: java binding guice

我是Guice的新手,并试图了解Module类中configure()方法的范围。目前以下是我的申请结构。有用。

class MainClass {
     public static void main(String[] args) {
         Injector injector = createInjector(new MainModule(param1, param2, param3));
         injector = injector.createChildInjector(injector.getInstance(FuncModule.class));

     }
}

FuncModule.java

 class FuncModule extends AbstractModule {

   @Override
   public void configure() {

         // Register a AWS SWF Workflow Worker
         // Register a AWS SWF Activity Worker

         // Instantiate WorkflowFactory class
         TempWorkflowClientExternalFactory obj = new TempWorkflowClientExternalFactoryImpl(<param1>, <param2>);
         bind(TempWorkflowClientExternalFactory.class).annotatedWith(Names.named("temp1")).toInstance(obj); 
   }
 }

我试图了解我的配置方法是否“过多”。配置方法的意图/范围仅限于绑定吗?如果是这样,哪里是注册工人和实例化工厂对象的最佳位置?

1 个答案:

答案 0 :(得分:1)

你想知道你的configure方法是否适合这种类型的初始化是正确的。这是一个判断问题。 Guice确实这样说:Modules should be fast and side-effect free.

  

但是Java语言的全部功能都需要付出代价:在模块中很容易做得太多。很容易连接到数据库连接或在Guice模块中启动HTTP服务器。不要这样做!在模块中进行繁重的工作会带来问题:

     
      
  • 模块启动,但它们不会关闭。如果您在模块中打开数据库连接,则不会有任何挂钩来关闭它。
  •   
  • 应该测试模块。如果模块打开数据库作为执行过程,就很难为它编写单元测试。
  •   
  • 可以覆盖模块。 Guice模块支持覆盖,允许生产服务替换为轻量级或测试服务。当生产服务作为模块执行的一部分创建时,此类覆盖无效。
  •   

要考虑的其他一些因素:

  1. 你的Guice模块仍然是一个Java类,可以而且应该和任何其他类一样遵守Single Responsibility Principle。如果依赖关系的构造或配置超过一两个屏幕,或者很难用一两句话描述,那么可能是时候拆分模块(参见install)或提取构造/配置对自己的方法或类。您已经向我们提供了评论configure部分的提示:也许是时候提取方法或类,以便代码更具自我描述性。

  2. Guice只是一个依赖注入框架,旨在需要非常少的Guice特定代码或模式。使用JSR330 - 兼容注释(@Inject)和接口(Provider),您应该能够手动复制或替换Guice的功能,或者使用不同的框架,如SpringDagger {{ 3}} - 没有太多麻烦。但是,Java模块实例是Guice独有的;如果您想在非Guice上下文中使用它,则需要对模块中的自定义初始化代码进行重构或重写。这可能是从一开始就将可重用的初始化代码与Guice模块分开的一个很好的理由。

  3. 与Guice wiki提到的类似,你应该在你的类中测试任何非平凡的逻辑。没有Guice,Guice模块及其configure方法很难测试;如果它是在一个单独的类或方法中,您可能会发现测试外部构造/配置更容易。

  4. 当您以未指定的顺序调用configurecreateInjector以及所有其他模块时,您在模块的createChildInjector方法中执行的任何初始化都会发生。这使得您只需很少的粒度来设置日志记录,顺从后台线程,优雅地catch异常,或以其他方式控制初始化发生的时间和方式。通过将第三方初始化程序代码提取到单独的类或方法,或者提供程序或@Provides方法,您可以更灵活地了解它的运行时间和方式。

  5. 所有这一切,Guice肯定允许实例绑定,并且在模块中看到简单和轻量级的构造函数调用,初始化程序调用和其他实例准备代码是很常见的。为几行简单的初始化创建一个全新的类可能有点过分。

  6. 简而言之,请保留简单/短/安全初始化调用,但只要事情变得复杂/冗长/危险就准备好提取创建或初始化以给自己更多控制。

    P.S。另外,虽然从Injector获取Module实例并没有技术错误,但请注意它不是常见的模式。充其量,这违反了您在模块configure时无法访问功能正常的注入器的经验法则;在最坏的情况下,您可能会发现很难说明您实际调用的是哪个Injector,因此您可以使用哪些绑定。您可以保留它,但要谨慎使用,并考虑通过将父素注入器源依赖项作为模块构造函数参数传递来保持显式。

    /** Injected child module. Get this from a parent injector. */
    public class BModule extends AbstractModule {
      @Inject Injector injector;  // You can always inject the Injector...
    
      @Override public void configure() {
        bind(B.class).to(BImpl.class);
      }
    
      @Provides C provideC(B b) {
        return new C(b);
      }
    
      @Provides D provideD() {
        return new D(injector.getInstance(B.class));  // but this won't work;
                                                      // injector is the parent,
                                                      // not the one with this module.
      }
    }