如何使用谷歌Guice注入依赖关系



我已经浏览了用户指南和所有内容,但我仍然不明白在尝试注入依赖项时如何修改现有代码以使用 Google Guice。因此,为了更容易,我创建了这个简单的例子,如果有人可以用这个简单的例子来解释,我将不胜感激!

假设我有一个

public Class A {
    private int count = 0;
    public A() {
    }
    public int getCount() {
      return count;
    }
    public void setCount(int newCount) {
      this.count = newCount;
    }
}

和另一个类

public Class B {
    private A objectA;
    public B() {
        objectA = new A();
    }
    public void messWithCount() {
        int tempCount = objectA.getCount();
        objectA.setCount(tempCount+1);
    }
}

所以基本上我的问题是:我将如何使用 Google Guice 在构造函数B()中提取objectA的创建,并将其作为依赖项注入到 B 类中,它相当于类似

@Inject    
public B() {
}  

我将如何实际将 A 的实例注入其中?

首先,B 不应该绑定到 A 类,而应该使用接口(例如 AInterface)。Guice 的要点是绑定同一接口的不同实现,而不绑定到某个类。

因此,让我们假设A类实现了AInterface

interface AInterface {
    public int getCount();
    public void setCount(int newCount);
}
class A implements AInterface {
    private int count   = 0;
    public A() {
        System.out.println("done!");
    }
    @Override
    public int getCount() {
        return count;
    }
    @Override
    public void setCount(int newCount) {
        this.count = newCount;
    }
}

现在你告诉它注入你的变量:

class B {
    @Inject
    private AInterface  objectA;
    public B() {}
    public void messWithCount() {
        int tempCount = objectA.getCount();
        objectA.setCount(tempCount + 1);
    }
}

我删除了静态修饰符,但如果你坚持让它保持静态,你需要使用 requestStaticInjection 来绑定

您将实现 A 绑定到名为 module 的特殊类中的接口 AInterface

class SimpleModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AInterface.class).to(A.class);
    }
}

现在你让Guice为你生成B。

public class Temptemp {
    public static void main(String[] args) {
        Injector i = Guice.createInjector(new SimpleModule());
        B b = i.getInstance(B.class);
    }
}

您可以通过两种方式将 A 注入 B 中,实际上有很多方法,但在您的问题的上下文中,我会说两种。

  1. 确保在模块中同时配置了 A 类和 B 类。遵循扩展 AbstractModule 的 condit 示例代码/类。

1.a

class B {
   @Inject
   private A a;
   public B() {
   }
}

1.b

class B {
    private A a;
    @Inject
    public B(A a) {
        this.a = a;
    }
}

这些都工作正常,但如果你想为 B 类编写测试,1.b 很有用。您的测试将模拟 A 类并创建 B 的实例。

class BTest {
    @Test
    public void testSomeMethodOfB() {
       A a = mock(A.class);
       B b = new B(a);
       //run some test on b;
    }
} 

下面是一个基于您已有内容的示例:

public class GuiceExample {
  static class A {
    private int count = 0;
    public A() {}
    public int getCount() {
      return count;
    }
    public void setCount(int newCount) {
      this.count = newCount;
    }
  }
  static class B {
    @Inject
    private static A objectA;
    public B() {}
    public void messWithCount() {
      int tempCount = objectA.getCount();
      objectA.setCount(tempCount+1);
    }
  }
  static class Module extends AbstractModule {
    @Override 
    protected void configure() {
      requestStaticInjection(B.class);
    }
  }
  @Test
  public void test() {
    Injector i = Guice.createInjector(new Module());
    B b = i.getInstance(B.class);
    //Do something with b
  }
}

但请注意,静态注入不是首选。你可以使 A 成为非静态的,Guice 仍然会注入字段。更"正确"的方法是删除requestStaticInjection调用并添加 A 作为构造参数,例如:

  static class B {
    private A objectA;
    @Inject
    public B(A objectA) {
      this.objectA = objectA;
    }
    ...
  }

最新更新