簡體   English   中英

有沒有辦法訪問以前創建的 Guice 注入器?

[英]Is there a way to access Guice injectors which have previously been created?

為一個新項目查看 Guice(和 Dagger)。 到目前為止,我看到的每個 Guice 教程都顯示了在開發人員需要 DI 來創建對象實例時創建的注入器。

網上看到的一個典型例子:

public static void main(String[] args) {
    Injector injector = Guice.createInjector(new BasicModule());
    Communication comms = injector.getInstance(Communication.class);
}

對我來說,這違背了 DI 的目的——在任何需要實例的地方,你將實例綁定到定義如何構建它的模塊。

有沒有辦法讓 Guice 創建一個類的實例,該類的模塊(依賴圖)之前已經定義給 Guice(例如,在應用程序啟動時?)。

我正在使用 Dropwizard.io 框架,因此在某些情況下,我無法完全控制類的構造方式,但希望能夠模擬我在該類中引用的依賴項。

完全相同的適用於 Dagger - 我很欣賞其中一個/兩個的示例。

編輯:多年來,我在 .NET 中使用過幾個 DI 框架,所以我將舉例說明我正在嘗試基於其中一個框架做什么。

例如,在 ASP.NET Core DI 實現中,在服務啟動時定義您希望 DI 能夠創建的服務。 通常你會要求 DI 給你一個實例,它是一個接口的實現。 所以在啟動時:

protected override void ConfigureAdditionalServices(IServiceCollection services)
{
    services.AddScoped<ITransactionService, TransactionService>();
}

其中IServiceCollection是定義給 DI 的服務集合。

因為 DI 與 ASP.NET 框架集成,從這一點開始,您通常可以定義一個接受ITransactionService的構造函數,DI 將為您提供它。

但是,如果您在不知道它的框架中使用 DI,則需要訪問當前的 ServiceProvider 實例,然后您可以要求 DI 創建您的對象,如下所示:

var transactionService = ServiceProvider.GetService<ITransactionService>();

我意識到這實現了Service Locator 反模式,但它仍然具有將我的代碼與具體類實現解耦的好處,並允許我在應用程序啟動時模擬它們以進行測試。

所以回到問題所以根據這種情況重申我的問題,我如何在我的代碼中的某個隨機點從 Guice 請求一個類?

我需要在此代碼中更改哪些內容才能使其正常工作?

public class TransactionModule extends AbstractModule {
  @Override 
  protected void configure() {
    bind(TransactionServiceBase.class).to(TransactionService.class);
  }
}

// At startup
Injector injector = Guice.createInjector(new TransactionModule());


// Then, somewhere in the application, to get an instance of TransactionService
TransactionServiceBase transactionService = (TransactionServiceBase)Guice.getInstance(TransactionServiceBase.class);

我認為您可能會誤解 Injector.getInstance - 就像您的示例有一個public static方法來開始一樣,即使您通常不會使用所有公共靜態方法編寫應用程序的其余部分(我希望),除了在極少數特定情況下,您也不會調用Injector.getInstance

相反,此代碼僅用於使事情順利進行。 另一個流行的“開始”是injector.injectMembers(this) - 讓main()手動創建一個實例,該實例是您的應用程序的基礎,帶有@Inject注釋的成員,然后只要求現在創建的 Injector填充成員。

當您繼續“向內”應用程序的其余部分時,您可能永遠不會再次引用 Injector 實例,而是依賴提供程序、輔助注入或只是 guice 創建的實例。

通過這種方式,您永遠不應該關心注入器或為其設置的確切模塊。 在應用程序的整個生命周期內應該只存在一個注入器(基本上沒有例外,除非您重新定義“應用程序”是什么),並且在 99% 的時間里它對您隱藏(例外:您的 DI滿足其他一些 DI,並且需要通過其類請求某事物的實例,或者您有工具想要內省所有聲明的綁定集)。 因此,您應該能夠只提供 setter、構造函數 args 或 init 方法,然后可以手動調用它們,或者讓任何 guice 上下文根據它們自己的特定模塊和規則創建它們。

我認為答案是沒有標准/支持的方法來做到這一點。

通常的假設是你有盡可能少的“注入”點,最好是一個,然后你通過創建依賴項構造函數參數來指定每個類需要什么。

我所知道的與您在此處描述的情況類似的唯一場景是 android 應用程序中的 Dagger。 他們解決這個問題的方法是將匕首“注入器”(sorta)存儲在一個全局對象 - 應用程序中,然后 Dagger 提供一個靜態函數來檢索該對象並執行注入。

長話短說 DI 框架不適用於您自己不實例化類的范式。

我能想到的唯一解決方案是將您的注入器存儲在某個全局變量中,並在您需要時從那里獲取它。

靜態注入可能對您的情況有所幫助https://github.com/google/guice/wiki/Injections#static-injections

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM