【问题标题】:How to create an instance of an implementation in Google Guice如何在 Google Guice 中创建实现的实例
【发布时间】:2015-10-09 11:19:27
【问题描述】:

我是 Google Guice 的新手,需要一点帮助。我创建了一个这样的模块:

public interface Foo {
  Bar doSomething();
}

public class MyFoo implements Foo {
  Bar doSomething() {
    // create an instance of MyBar
  }
}

public interface Bar {
  void run();
}

public interface MyBar implements Bar {
  void run();
}

public class MyModule extends AbstractModule {

  @Override
  protected void configure() {
    bind(Foo.class).to(MyFoo.class);
  }      
}

我的问题是:在“MyFoo”类中创建 MyBar 实例的正确方法是什么?这样做感觉不对:

public class MyFoo implements Foo {
  Bar doSomething() {
    MyBar mybar = new MyBar();
    return mybar;
  }
}

有没有办法在我需要的时候通过 MyModule 注入一个新的 MyBar 实例,或者我必须在 MyBar 的构造函数中注入一个工厂来创建 MyBar 实例? 如果我必须使用工厂,我可以控制通过模块生成哪个实现吗?

【问题讨论】:

    标签: java dependency-injection guice inject


    【解决方案1】:

    您可以使用 Setter 或 Constructor Injection ,如下所示:

    public class MyFoo implements Foo {
    
        //constructor based injector
        @Inject
        public MyFoo(MyBar myBar){
            this.myBar=myBar;
        }
    
         //setter method injector
        @Inject
        public void setBar(MyBar myBar){
            this.myBar=myBar;
        }
    
        Bar doSomething() {
        // create an instance of MyBar
      }
    }
    

    MyBar 在您的情况下是 Interface which can not be instantiated ,您必须为此提供具体的实现,然后绑定到您的 Module 中,并如上所述通过 Setter 或 Constructor Injection 注入它。

    Setter 注入示例:

    MyModule.java

    import com.google.inject.AbstractModule;
    
    public class MyModule extends AbstractModule {
    
        @Override
        protected void configure() {
            bind(Foo.class).to(MyFoo.class);
            bind(Bar.class).to(MyBar.class);
        }
    }
    

    MyBar.java

    public class MyBar implements Bar {
    
        public void run() {
            System.out.println("Hello Bar");
        }
    }
    

    MyFoo.java

    import com.google.inject.Inject;
    
    public class MyFoo implements Foo {
        private Bar bar;
    
        // setter method injector
        @Inject
        public void setBar(Bar myBar) {
            this.bar = myBar;
        }
    
        public Bar doSomething() {
            return bar;
        }
    }
    

    【讨论】:

    • MyBar 不是我想要注入的东西。 doSomething() 方法必须创建 MyBar 的一个实例并返回它。
    【解决方案2】:

    也许您正在寻找供应商?提供者或多或少是属于 Guice API 一部分的工厂,因此您不必实现它们。

    public class MyFoo implements Foo {
      @Inject Provider<MyBar> myBarProvider;
    
      Bar doSomething() {
        return myBarProvider.get(); // returns a new instance of MyBar
      }
    }
    

    详情见https://github.com/google/guice/wiki/InjectingProviders

    【讨论】:

    • 正是我想要的。谢谢
    • 值得一提,这是在 guice 中实现复杂生命周期处理的第一步。将来您可能会发现自己使用更多提供商并遇到困难(我遇到过)。解决我的问题的两个关键问题是@Assistedinject(当您需要调用提供者但您还需要为该提供者提供一些上下文(即 args)以帮助 guice 解决依赖关系时),以及显式提供者方法,( github.com/google/guice/wiki/ProvidesMethods),当您需要做的不仅仅是简单地让 guice 调用构造函数(这里的日志记录似乎是一个常见问题)
    猜你喜欢
    • 2015-08-19
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多