java - Guice配置范围

标签 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); 
   }
 }

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

最佳答案

您有理由怀疑您的 configure 方法是否适合进行此类初始化;这是一个判断问题。 Guice 确实有这样的说法:Modules should be fast and side-effect free.

But the full power of the Java language comes at a cost: it's easy to do too much in a module. It's tempting to connect to a database connection or to start an HTTP server in your Guice module. Don't do this! Doing heavy-lifting in a module poses problems:

  • Modules start up, but they don't shut down. Should you open a database connection in your module, you won't have any hook to close it.
  • Modules should be tested. If a module opens a database as a course of execution, it becomes difficult to write unit tests for it.
  • Modules can be overridden. Guice modules support overrides, allowing a production service to be substituted with a lightweight or test one. When the production service is created as a part of module execution, such overrides are ineffective.

需要考虑的其他一些因素:

  1. 您的 Guice 模块仍然是一个 Java 类,并且可以而且应该遵守 Single Responsibility Principle与任何其他类(class)一样。如果您的依赖项的构造或配置超过一两个屏幕,或者很难用一两句话来描述,那么可能是时候分解该模块(请参阅 install )或将构造/配置提取到其自己的方法或类。您通过注释的 configure 部分向我们提供了提示:也许是时候提取方法或类,以便代码更具自描述性。

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

  3. 沿着类似的思路,正如 Guice wiki 提到的那样,您应该在类中测试任何重要的逻辑。如果没有 Guice,Guice 模块及其配置方法很难进行测试;如果您的外部构造/配置位于单独的类或方法中,您可能会发现更容易测试它。

  4. 当您调用 createInjectorcreateChildInjector 时,您在模块的 configure 方法中执行的任何初始化都会发生,以及调用中的所有其他模块未指定的订单。这为您提供了非常小的粒度来设置日志记录、遵循后台线程、优雅地捕获异常或以其他方式控制初始化发生的时间和方式。通过将第三方初始化程序代码提取到单独的类或方法,或者 Provider 或 @Provides 方法,您可以更灵活地了解其运行时间和方式。

  5. 总而言之,Guice 绝对允许实例绑定(bind),并且在模块中看到简单且轻量级的构造函数调用、初始化程序调用和其他实例准备代码是很常见的。为几行琐碎的初始化创建一个全新的类可能有点过分了。

简而言之,保留简单/简短/安全的初始化调用,但一旦事情变得复杂/漫长/危险,就准备好提取创建或初始化,以便给自己更多的控制权。

<小时/>

附注另外,虽然从注入(inject)器获取 Module 实例在技术上没有任何问题,但请注意这不是常见模式。充其量,这违反了您在模块配置时无权访问正常运行的注入(inject)器的经验法则;在最坏的情况下,您可能会发现很难推断出您实际调用的是哪个注入(inject)器,以及您可以使用哪些绑定(bind)。您可以保留它,但请谨慎使用,并考虑通过将父注入(inject)器来源的依赖项作为模块构造函数参数传递来保持显式。

/** 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.
  }
}

关于java - Guice配置范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38881520/

相关文章:

binding - Clojure 绑定(bind)不起作用

guice - 将参数传递给 Guice @Provides 方法

java - 查询结果在 'Syntax error at end of input' (java/Postgres)

java - Java 中没有 setter 方法可以访问私有(private)数据字段吗?

WPF 将父绑定(bind)对象传递给转换器

android - Roboguice 在 JUnit 测试中不工作

Java Guice - toProvider 方法不适用于参数

java - Eclipse 运行配置中的通配符扩展

java - Gradle 5 和 IntelliJ 2018.3。无法识别的选项 : --add-opens or java. base.java.lang=ALL-UNNAMED

WPF DataGrid ItemsSource 绑定(bind)问题