中文字幕一区二区人妻电影,亚洲av无码一区二区乱子伦as ,亚洲精品无码永久在线观看,亚洲成aⅴ人片久青草影院按摩,亚洲黑人巨大videos

使用Dagger框架進行依賴注入

發(fā)布于:2021-01-11 11:31:11

0

98

0

Dagger 框架 依賴注入

Dagger愛好者Sven Ruppert在一個簡單的示例中演示了依賴注入,該示例旨在聲明依賴,指定如何滿足依賴以及讓您專注于有趣的類。

Dagger是基于Guice的開源依賴項注入(DI)框架。但是,Dagger的開發(fā)人員對Guice的基本原理并不滿意:他們不得不一次又一次地在較大的項目中編寫代碼,其中涉及大量的綁定代碼。由于這是靜態(tài)語義的一部分,因此他們的策略是提取此綁定并將其以源代碼形式存儲。

Dagger開發(fā)人員還需要易于閱讀且支持調試過程的內(nèi)容。下面我們更仔細地研究Dagger并開始探索該框架。我們的示例基于 Dagger 1.2版。

用Dagger進行依賴注入

Dagger的怪癖之一是其在Java和Android系統(tǒng)中的可用性。讓我們看一個簡單的示例,并從Main類中的簡單@Inject實例(Main Service)開始:

public class Main {   @Inject MainService mainService;   /.. } public interface MainService {   public String execute(String txt); } public class MainServiceImpl implements MainService {   public String execute(String txt){     return "MainServiceImpl _ " + txt;   } }

為了獲得具有注入屬性的類的實例,需要使用ObjectGraph。ObjectGraph是實例化所必需的所有依賴項的表示。在下面的示例中,我們可以在Main類中看到Dagger的初始化和使用:

public class Main {  @Inject MainService mainService;     public static void main(String[] args) {     //bootstrapping     ObjectGraph objectGraph         = ObjectGraph.create(new BusinessModule());     Main main = objectGraph.get(Main.class); //    Main main = new Main(); //    objectGraph.inject(main);     System.out.println("execute = " + main.mainService.execute("Go"));     System.out.println("execute = " + main.mainService.execute("Go"));     System.out.println("execute = " + main.mainService.execute("Go"));   } }

Dagger通過兩種方式訪問包含注入的屬性的類的實例。一種方法是通過ObjectGraph類的get(..)方法直接提供一個就緒實例。另一種方法是通過顯式調用方法inject(..)  ,該方法可以應用于現(xiàn)有實例。這使您可以控制在生成保持類實例與成員本身之間的時間。

注意事項:為了生成ObjectGraph類的實例,需要create(..)方法的參數(shù)  或模塊。在我們的例子中,我們創(chuàng)建了 BusinessModule()。在此模塊中,定義了它們之間的依賴關系,還使用了生產(chǎn)者。

@Module(library = false, injects = {Main.class}, complete = true) public class BusinessModule {   @Provides   MainService provideMainService() {     return new MainServiceImpl();   } }

生產(chǎn)者既可以在實例本身中生成,也可以在方法參數(shù)上使用注入(如下)。請注意,Dagger必須使用新的構造函數(shù)-如果要創(chuàng)建的實例本身沒有注入的屬性-或已通過帶有注入屬性的方法參數(shù)傳遞了實例。

@Provides MainService provideMainService(MainServiceImpl mainService) {   return mainService; }

內(nèi)部功能

開發(fā)人員很快就會提出的基本問題涉及到依賴項的定義。Java中有幾種定義依賴關系的方法–如果依賴關系很明確,則通常很容易。當涉及區(qū)分或多重性時,它將變得更加復雜。

以類似SubService的接口為例 。對于此接口,有兩種實現(xiàn):SubServiceA和SubServiceB。如果我們將 @Inject SubService 放在源代碼中,則實現(xiàn)不清楚。在下文中,我們假定它將始終生成一個實例,該實例已使用注釋@Produces管理了相應的方法ProvideXXX(在我們的示例中為offerMainService())。這是工廠方法。

public class MainServiceImpl implements MainService {   @Inject SubService subService;   public String execute(String txt){     return subService.work(txt);   } }

還需要一種用于創(chuàng)建SubService實例的工廠方法。在這里,您可以選擇應使用的實現(xiàn)(SubServiceA或 SubServiceB)。當然,這是一個靜態(tài)的決定。在稍后的階段,我們將使其動態(tài)化。

@Provides SubService provideSubService() {   return new SubServiceA(); }

反射和配置

但是Dagger可以識別在哪里使用哪個實例嗎?反射或配置是這里的答案。在某些框架中,使用配置方法。然后讀取此配置,并將其用作實例化的基礎。不幸的是,由于這些方法麻煩且容易出錯,因此可能會出現(xiàn)問題。

另一種選擇是反射。在運行時,我們可以確定哪個類具有依賴關系,但是,在這種情況下,我們尚未解決多重性問題。 為此,JSR-330具有限定符@Named(..)。這將允許您輸入相應的實現(xiàn)名稱,然后在解析中使用它們。 SubServiceA 將被實現(xiàn)為 @Named(“A”)和SubServiceB與@Named(“B”) 。一旦指定了限定詞,我們就定義了 @Inject:

@Inject @Named("A") SubService subservice;

@Named(“ A”)也提供了隨附的工廠方法。這是關于將類/接口和注釋相結合,然后進行匹配的所有內(nèi)容:

@Inject SubService subservice

您不要忘記,仍然需要編寫沒有限定符的工廠方法。

@Module(library = false, injects = {Main.class},complete = true) public class BusinessModule {   @Provides   MainService provideMainService(MainServiceImpl mainService) {     return mainService;   }   @Provides @Named("A")   SubService provideSubServiceA() {     return new SubServiceA();   }   @Provides @Named("B")   SubService provideSubServiceB() {     return new SubServiceB();   }   @Provides   SubService provideSubService(@Named("A") SubService subServiceA) {     return subServiceA;   } }

現(xiàn)在如何以及何時檢測到依賴關系?這可以使用反射在運行時完成。Dagger是一個略有不同的框架:使用了反射,但它不是運行時,而是參與了編譯過程。使用反射解決依賴關系并進行檢查,此過程會產(chǎn)生不同的結果。首先,具有擴展名的文件點應用,在那里你可以閱讀有關發(fā)現(xiàn)的依賴關系。請參閱以下內(nèi)容:

digraph G1 {   concentrate = true;   Main -> MainService;   MainService -> MainServiceImpl;   MainServiceImpl -> SubService;   n2 [label="@javax.inject.Named(value=A)            /org.rapidpm.demo.dagger.business.subservice.SubService"];   SubService -> n2; }

這些化合物很容易識別。但是生成了哪些類?這是指:Main $$ InjectAdapter,MainServiceImpl $$ InjectAdapter和BusinessModule $$ ModuleAdapter。

讓我們從Main $$ InjectAdapter類開始。適配器提供了一個get()方法,該方法返回一個已實例化的引用。在這里,您可以看到確切的生命周期-而且很容易管理。它包括兩個步驟:首先,創(chuàng)建實例,其次,合并injectMembers(..)方法。

此外,該化合物還適用于其他類別。為了確保所有內(nèi)容都保持靜態(tài)語義,并在運行時調用相應的Getter。與Reflection相比,此方法在運行時效率更高。因此,此適配器類形成了完整的綁定,其中包括應用程序的所有組合和變體。