使用具有循环依赖关系的Guice

Yur*_*nov 9 dependency-injection guice

考虑这个简单的例子.

Class A {
   B b;
   A() {
       this.b = new B(this);
   }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,实例A知道实例B,而实例B知道实例A.

我的问题是:如何使用Guice实例化实例A,即如何让Guice处理这个复杂的循环依赖?

Col*_*inD 10

您的示例根本不是问题,因为您直接构建B.但是如果你想要由Guice创建A和B,则一个或两个应该是一个接口.你可以做:

public interface A { /* skipping methods */ }
public interface B { /* skipping methods */ }

public class AImpl implements A {
   private final B b;

   @Inject
   public AImpl(B b) {
      this.b = b;
   }
   // ...
}

public class BImpl implements B {
   private final A a;

   @Inject
   public BImpl(A a) {
      this.a = a;
   }
   // ...
}
Run Code Online (Sandbox Code Playgroud)

即使AImpl并且BImpl作为单身人士,Guice也可以处理这种注射(通过代理).无论如何,这在一个简单的情况下工作......我想可能有更复杂的循环依赖,它无法处理.无论如何,当然,消除循环依赖是更可取的.


Yur*_*nov 5

答案是当你的代码中有循环依赖时你不应该使用依赖注入框架

所以,你必须事先重构你的代码。据我所知,紧密耦合的类有两种解决方案:将两个类合并为一个或引入新类并将公共逻辑移入其中(详细信息请看这里


Nam*_*ter 4

回答你的第一个问题"如何用Guice实例化实例A":你可以简单地添加@Inject到构造函数:

class A {
   private final B b;

   @Inject
   A() {
       this.b = new B(this);
   }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为用于创建的API A没有循环依赖关系.只要A需要创建或注入A对象,Guice就会使用构造函数.

如果您的问题是如何使用Guice创建一个对象,其中用于创建对象的API具有循环依赖关系,请参阅Misko Hevery的这篇博文(如Yury的回答中所述).

  • 你甚至不需要@Inject用于no-args构造函数. (3认同)