インスタンス化を制御できないクラスを注入する最良の方法は?
-
26-10-2019 - |
質問
私はGuiceにかなり新しいので、これが明らかな質問ではないことを願っています...
アプリケーションクラスの1つを動的にインスタンス化するフレームワークを扱っています(電話してみましょう C
)反射を使用して、そのインスタンスを制御できません。さらに、新しく作成された私がアクセスする簡単な方法はありません C
フレームワークがインスタンス化された後。これが何ですか C
見た目:
public class C implements I { public C() { // this ctor is invoked by the framework so can't use DI here? } public void initialize() { // this is a post instantiation hook which the f/w will invoke } private void m() { Dependency d = Dependency.getInstance(); d.doSmth(); } }
をお願いします。 C
取得する Dependency
DIを使用します。ここ Dependency
明らかにシングルトンですが、これは一般的にそうである必要はありません。
私は2つの可能なソリューションを思いつきましたが、どちらも非常に整頓されていないので、専門家に尋ねると思いました。
静的注射。私は、これがサービスロケーターのアンチパターンでどのように劇的に改善するかを見るのに苦労しています - 私は外部から操作できる最終的な静的フィールドでないことになります...うーん。
フレームワークはフックをサポートしています
C
インスタンス化を初期化するにはinitialize()
上記の方法)。この方法は、セッターインジェクションを使用して、新しく作成されたインスタンスを自己挿入できます。
2では、これはより外部の変更性を意味すると思いますが、少なくとも単体テストのようなものについては依存関係をもう少し明示的に公開します。トラブルは次のとおりです。その場合、Guice Injectorを手に入れるにはどうすればよいですか(さらに別のサービスロケーターに依存していない)?また、APPコード全体でインジェクターを明示的に参照することは疑わしい練習であることを読みました(そして同意する傾向があります)。
あなたの洞察は本当に感謝しています。
どうもありがとう、
キリスト教徒
解決
プロバイダーを静的に噴射してCを試してみることができます。静的注入はテストするのがより厄介です。しかし、プロバイダーは、Guiceが怠lazに作成しながら、依存関係を熱心に検証することを可能にします。
public class C implements I {
@Inject static Provider<Dep1> dep1Provider;
@Inject static Provider<Dep2> dep2Provider;
...
public void initialize() {
Dep1 dep1 = dep1Provider.get();
Dep2 dep2 = dep2Provider.get();
...
}
}
他のヒント
Guiceインジェクターを静的変数および静的アクセサの方法で利用できるようにすると、次のように解決できます。
public class C implements I {
public C() {
// this ctor is invoked by the framework, you can't do injection here.
}
public void initialize() {
MyGuice.getInjector().inject(this);
}
@Inject
protected void init(Dep1 dep1, Dep2 dep2) {
this.dep1 = dep1;
this.dep2 = dep2;
}
private void m() {
dept1.doSmth();
}
}
静的呼び出しは少しパターンです。コードウェービングまたはポストコンパイルステップを使用するソリューションを使用する場合は、ポストコンストラクターインジェクションの世話をする簡単な注釈でその依存関係を削除できます。これにより、初期化メソッドがない場合でも、すべてのオブジェクトを挿入できます。この例をここで見つけることができます: AspectJを使用してモデルオブジェクトを注入する方法.
@Configurable
public class C implements I {
public C() {
// this ctor is invoked by the framework, you can't do injection here.
}
@Inject
protected void init(Dep1 dep1, Dep2 dep2) {
this.dep1 = dep1;
this.dep2 = dep2;
}
private void m() {
dept1.doSmth();
}
}