2017-04-14 52 views
1

我有一個名爲Legacy的現有類,主要是用舊式單例模式編寫的。現在我想介紹一個新的領域,我想用Guice。 Legacy本身不受Guice控制,它被另一個Service類使用(在Service類中,它調用Legacy類的getInstance()以立即檢索Legacy對象),並且該Service類是使用Guice注入器創建的。如何在現有的單例類中使用guice注入?

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注入我的程序的任何想法,但保持目前的老派單身模式,而不是改變太多的一切?

編輯 下面至少有三個解決方案,我不知道哪個是最好的或他們是否等價。

+1

這三種解決方案或多或少都是相同的。他們都直接或間接地調用'injectMembers'在你的單身人士身上。 –

回答

1

這是一個有點駭人聽聞的解決方案。

在應用程序的引導, 可能在方法public static void main(String[] args), 你應該已經有類似下面的代碼:

Injector injector = Guice.createInjector(yourModule); 

在這個地方添加以下行:

injector.injectMembers(Legacy.getInstance()); 

通過這樣做,您的Legacy單身人士 中的所有@Inject都應該解決。
另請參閱Injector.injectMembers的javadoc。

2

雖然只比托馬斯的答案稍微乾淨一點,但您可以使用requestInjectionrequestStaticInjection來配置從您的模塊中注入單身人士。

// 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()); 

在這個例子中,你的模塊本身,而不是吉斯,需要獲得一個傳統實例的責任,然後要求吉斯一直使用這個單一實例來滿足所有遺留注入請求。 但根據javadoc 創建Injector時,它將自動爲此實例執行字段和方法注入,但Legacy上的任何可注入構造函數都被忽略。請注意,使用這種方法會導致您無法控制的「急切加載」行爲。

+0

這個解決方案還有其他的好處,你甚至可以使用'@Inject Legay legacy'來將你的單例注入其他類。 –