循環依存関係とのGuiceを使います
-
18-09-2019 - |
質問
この単純な例を考えてみましょう。
Class A {
B b;
A() {
this.b = new B(this);
}
}
この例の場合においてAは、インスタンスBを知っている、およびインスタンスBは、インスタンスAを知っている。
の私の質問は次のとおりです。のGuiceのでインスタンスAをインスタンス化する方法、すなわち、どのようにGuiceのは、この複雑なサークルの依存関係の世話を作るために、
?解決
@Inject
を追加することができます: このあなたの最初の質問「どのようにGuiceのでインスタンスAをインスタンス化する」を答えるために
class A {
private final B b;
@Inject
A() {
this.b = new B(this);
}
}
A
を作成するためのAPIは、円形の依存関係を持っていないため、この作品。 Guiceのは、ちょうどA
コンストラクタにそれがA
オブジェクトを作成したり、注入する必要があるすべての時間を使用します。
あなたの質問は、<のhref = "http://misko.hevery.com/2008/08/01/circular参照、オブジェクトを作成するためのAPIは、循環依存関係を持つオブジェクトを作成するために、Guiceのを使用する方法である場合-dependency・イン・コンストラクタ-と依存性注入/」のrel = "nofollowをnoreferrer"> Misko Hevery の(ユーリの答えで述べたように)。することによって、このブログの記事
他のヒント
あなたの例では、まったく問題ではありません。あなたは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;
}
// ...
}
AImpl
とBImpl
がシングルトンとしてスコープされている場合でも、Guiceのは、(プロキシを介して)この注入を扱うことができます。これは私がそれを扱うことができなかった、より複雑な循環依存関係があるかもしれないと想像...いずれにせよ、このような単純なケースで動作します。とにかく、円形の依存性を排除することはもちろん、好ましいであろう。
答えはあなたのコードでの円形の依存関係を持っていながら、を使用すると、依存性注入フレームワークを使うべきではないということです。
だから、あなたは予めごコードをリファクタリングする必要があります。詳細ルック<のhref = "http://misko.hevery.com/のための1に2つのクラスをマージしたり、新しいクラスを導入し、その中に共通のロジックを動かすのいずれか(:私の知る限りでは、密結合のクラスには2つのソリューションがあります2008/8月1日/円形依存型コンストラクタアンド依存性注入/」REL = 『nofollowをnoreferrer』>こちら)
私はNamshubWriterの提案は非常にguicyではないと思われます。フィールドにパラメータを割り当てる:私はGuiceの中で、コンストラクタは正確に一つのことを行うべきだと思います。あなたがする必要がある何かがある場合、工場またはプロバイダにそれを置きます。
この場合、我々はA.のプロバイダをプロバイダが直接新しいBを呼び出すことができます()、しかし、我々は、我々は最初の場所で避けることを試みたものですBに直接カップルAと思いたくなるでしょう。 GuiceのはassistedInjectを経由して私たちのために提供することができ、工場、オーバーBのだから我々は間接的な創造。このコードは、実行され、微細なコンパイル、および完全に切り離さAとB
現実的なシナリオでは、あなたは分離を利用するインタフェースの後ろにAとBを非表示にする必要があると思います。
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryProvider;
public class Try {
public static void main(String[] args) {
System.out.println(
Guice.createInjector(new MyModule()).getInstance(A.class)
);
}
}
class MyModule extends AbstractModule {
public void configure() {
bind(A.class).toProvider(AProvider.class);
bind(IBFactory.class).toProvider(
FactoryProvider.newFactory(IBFactory.class, B.class));
}
}
class A {
B b;
public void setB(B b) {
this.b = b;
}
}
class B {
A a;
@Inject
B(@Assisted A a) {
this.a = a;
}
}
class AProvider implements Provider<A> {
private final IBFactory bFactory;
@Inject
AProvider(IBFactory bFactory) {
this.bFactory = bFactory;
}
public A get() {
A a = new A();
a.setB(bFactory.create(a));
return a;
}
}
interface IBFactory {
public B create(A a);
}