2017-04-14 2 views
1

私はレガシーという名前の既存のクラスを持っていますが、これはほとんどが古い学校のシングルトンパターンで書かれています。今私はそれに新しいフィールドを導入したい、私はGuiceを使用したいと思います。レガシー自体はGuiceコントロールではなく、別のServiceクラス(サービスクラス内ではレガシークラスのgetInstance()を呼び出してレガシーオブジェクトを取得しています)によって使用され、そのサービスクラスはGuiceインジェクタを使用して作成されています。私が試した何既存のシングルトンクラスにguice injectionを使用するには?

public class Legacy { 

    public synchronized static Legacy getInstance() { 
     if(sInstance == null) { 
      sInstance = new Legacy(); 
     } 
     return sInstance; 
    } 

    private Legacy() { 
     legacyObj = LegacyField.getInstance(); // get a singleton 
    } 

    private static Legacy sInstance; 

    private LegacyField legacyObj; 

    private NewField newObj; // this is the new dependency I would like to add using Guice 
} 

が、私はこの方法は、レガシークラス

@Inject 
public void setNewField(NewField newObj) { 
    this.newObj = newObj; 
} 

へとサービスのモジュールファイルに注入し入れてみましたということで、私はニューフィールドオブジェクトを結合するが、私はプログラムを実行すると、それはNullPointer例外をスローしました。だから注射がうまくいかない。私のプログラムにNewFieldを注入する方法はありますが、現在の古い学校のシングルトンのパラダイムを維持し、それ以外は何も変えないでください。

EDIT 以下の解決策は少なくとも3つありますが、どちらが最適か、それとも同等かはわかりません。

+1

3つのソリューションは多かれ少なかれ同等です。彼らはあなたのシングルトンに(直接的または間接的に) 'injectMembers'を呼び出します。 –

答えて

1

これはややハックのある解決策です。アプリケーションのブートストラップで

、 は方法public static void main(String[] args)であってもよく、 あなたはすでにこのようなコードが必要です。

injector.injectMembers(Legacy.getInstance()); 

:次の行を追加します。この場所で

Injector injector = Guice.createInjector(yourModule); 

をそうすることで、Legacyシングルトン にある@Injectのすべてを解決する必要があります。
Injector.injectMembersのjavadocも参照してください。

2

トーマスの回答よりもわずかに清潔ですが、requestInjectionまたはrequestStaticInjectionを使用して、モジュール内からシングルトンの注入を設定できます。

// In your Module: 
requestInjection(Legacy.getInstance()); // for an instance field, or 
requestStaticInjection(Legacy.class); // for a static field. 

docs on the wikiはしかし、欠点について警告:

それは静的な工場と同じ問題の多くを被るため、このAPIは、一般的な使用は推奨されません:それはテストに不器用だし、それが依存関係を作ります不透明で、グローバルな状態に依存します。

3

私はちょうど別の解決策が見つかりました:この例では

// put in the module 
bind(Legacy.class).toInstance(Legacy.getInstance()); 

を、あなたのモジュール自体ではなく、Guiceのは、レガシーインスタンスを取得するための責任を取り、その後、常にすべてを満たすために、この単一のインスタンスを使用するようにGuiceのを頼みますレガシー噴射要求。 しかし、javadoc によると、インジェクタが作成されると、このインスタンスのフィールドとメソッドの注入が自動的に実行されますが、レガシーの注入可能なコンストラクタは単に無視されます。このアプローチを使用すると、制御できない "熱心な読み込み"の結果になることに注意してください。

+0

このソリューションには、シングルトンを他のクラスに注入するために '@Inject Legay legacy; 'を使用することもできるというさらなる利点があります。 –

関連する問題