Google Guice结合模式
要創建綁定(Binding)對象,能夠繼承自AbstractModule類,然后覆蓋其configure方法,在方法調用bind()方法來指來定每一次綁定。這些方法帶有類型檢查,假設你使用了錯誤的類型編譯器就會報告編譯錯誤。假設你已經寫好了Module類,則創建一個Module類對象作為參數傳遞給Guice.createInjector()方法用于創建一個注入器。
通過Module對象能夠創建鏈接綁定(linked bindings)、實例綁定(instance bindings)、@Provides methods、提供者綁定(provider bindings)、構建方法綁定(constructor bindings)與無目標綁定(untargetted bindings)。
這些綁定方式統稱為內置綁定,相相應的還有種及時綁定。假設在解析一個依賴時假設在內置綁定中無法找到。那么Guice將會創建一個及時綁定。
一、鏈接綁定(LinkdedBindings)
鏈接綁定即映射一類型到它的實現類,比如映射TransactionLog接口到實現類DatabaseTransactionLog:
public class BillingModule extends AbstractModule {@Override protected void configure() {bind(TransactionLog.class).to(DatabaseTransactionLog.class);} }
這樣,當你調用injector.getInstance(TransactionLog.class)方法,或者當注入器碰到TransactionLog依賴時,就會使用DatabaseTransactionLog對象。鏈接是從一類型到它不論什么的子類型,這包含接口實現類,類的子類;所以例如以下映射也是能夠的:bind(DatabaseTransactionLog.class).to(MySqlDatabaseTransactionLog.class);
而且鏈接綁定支持鏈式寫法:
在這樣的情況下,當請求一個TransactionLog類型對象時,注入器將返回一個MySqlDatabaseTransactionLog對象。
二、綁定注解
某些情況下你可能想為同一種類型設置多種綁定。這就能夠通過綁定注解來實現,該注解與綁定的類型用于唯一結識一個綁定,
合在一起稱為Key。演示樣例:
這里關鍵的是@BindingAnnotation元注解,當Guice描寫敘述到該注解時,就會把PayPal作為綁定注解。
然后在Module的configure方法中使用annotatedWith語句,例如以下:
bind(CreditCardProcessor.class).annotatedWith(PayPal.class).to(PayPalCreditCardProcessor.class);
這樣就把CreditCardProcessor映射到了PayPalCreditCardProcessor。
使用方法:
另一種情況,我們能夠使用Guice已經定義好的@Named注解。比如:
要綁定一詳細名稱,使用Names.named()來創建一個實現傳給annotatedWith方法:
bind(CreditCardProcessor.class).annotatedWith(Names.named("Checkout")).to(CheckoutCreditCardProcessor.class);
由于編譯器不會對字符串進行檢查,Guice建議我們少使用@Named注解,可是我個人覺得,僅僅要自己寫代碼時僅僅要名稱不要寫錯,
通過這樣的方法式是最easy為同一類型映射多個綁定的。這非常類似Spring中的實現方式,Spring的@Service,@Controller,@Repository不就能夠指定名稱嗎?
三、實例綁定(Instance Bindings)
通過實例綁定我們能夠為某類型綁定一個詳細的實例,這只適用于這些實例類型沒有其他依賴的情況,比如值對象:
bind(String.class).annotatedWith(Names.named("JDBC URL")).toInstance("jdbc:mysql://localhost/pizza");bind(Integer.class).annotatedWith(Names.named("login timeout seconds")).toInstance(10);
使用方式:
@Inject @Named("JDBC URL") private String urlGuice建議我們避免使用.toInstance來創建復雜的對象。由于這會延遲應用啟動。類似地,能夠使用@Provides方法實現。
四、@Provides方法
當使用@Provides方法創建對象時。該方法必須定義在Module類中。而且它必須加以@Provides注解。該方法的返回值類型就是被綁定的對象。
當注入器須要該類型的實例時,它就會來調用該方法。
假設在@Provides方法上有@PayPal或@Named("Checkout")綁定注解。Guice以綁定注解優先。Guice在調用@Provides方法之前會先解析該方法的依賴:
關于異常:
Guice不同意在@Provides方法中拋出異常。
假設有異常拋出。那么異常將會被包裝在ProvisionException對象中。
五、提供者綁定(Provider Bindings)
假設@Provides方法越來越復雜。我們可能會想把它們移到一個單獨的類中。一個提供者類實現了Provider接口。它是一個
用于提供值的簡單通用接口。
假設提供者實現類有其自己的依賴時,能夠通過在其構造方法上加入@Inject注解進行注入,以保證值安全返回。
最后使用.toProvider語句來綁定到提供者:
public class BillingModule extends AbstractModule {@Overrideprotected void configure() {bind(TransactionLog.class).toProvider(DatabaseTransactionLogProvider.class);} }
六、無目標綁定
Guice同意我們創建綁定時不指定目標類。也就是沒有to語句,這對于詳細類或者使用了@ImplementedBy或@ProvidedBy注解類型非常實用。比如:
bind(MyConcreteClass.class);
bind(AnotherConcreteClass.class).in(Singleton.class);
然而,在使用綁定注解時,我們依賴必須指定綁定目標。即它是一個詳細類,比如:
bind(MyConcreteClass.class).annotatedWith(Names.named("foo")).to(MyConcreteClass.class); bind(AnotherConcreteClass.class).annotatedWith(Names.named("foo")).to(AnotherConcreteClass.class).in(Singleton.class);
七、構造方法綁定
有些時候你可能須要將某一類型綁定到任一構建方法,比如在@Inject注解無法加入到目標類構造方法,其原因可能是這個類是
第三方提供的。或者說該類有多個構建方法參與依賴注入。此時@Provides方法是解決問題的最好方案,由于它能夠明白指定
調用哪個構造方法。并且不須要使用反射機制。
可是使用@Provides方法在某些地方有限制,比如:手動創建對象不能在AOP中使用。
正是由于這個原因,Guice使用了toConstructor()進行綁定。這須要我們使用反射來選擇構造方法與處理異常。
public class BillingModule extends AbstractModule {@Override protected void configure() {try {bind(TransactionLog.class).toConstructor(DatabaseTransactionLog.class.getConstructor(DatabaseConnection.class));} catch (NoSuchMethodException e) {addError(e);}} }
上這個樣例中DatabaseTransactionLog類必須有一個帶DatabaseConnection參數的構造方法,該構造方法中不須要使用@Inject注解Guice會自己主動調用該構造方法。每一條toConstructor()語句創建的綁定。其作用域是獨立的,假設你創建了多個單例綁定而且使用目標類的同一個構造方法,每個綁定還是擁有各自的實例。
八、及時綁定
當注入器須要某一類型實例的時候。它須要獲取一個綁定。在Module類中的綁定叫做顯示綁定,僅僅要它們可用,注入器就能夠使用它們。假設須要某一類型實例,但它又不是顯示綁定。那么注入器將試圖創建一個及時綁定(Just-In-Time bindings),它也被稱為JIT綁定與隱式綁定。
可用于創建及時綁定的情況例如以下:
a.有一個合適的構建方法,即非私有。不帶參數或者標有@Inject注解的構造方法,比如:
Guice不會創建內部類實例除非它有static修飾符,由于內部類含有一個指向外問類的隱式引用,而這個隱式引用無法注入。
b. @ImplementedBy
@ImplementedBy注解于用告訴注入器某類型的缺省實現類型是什么,這與鏈接綁定非常相似。
為某一類型綁定一子類型例如以下:
@ImplementedBy(PayPalCreditCardProcessor.class)等效于以下的bind()語句:
bind(CreditCardProcessor.class).to(PayPalCreditCardProcessor.class);
假設某一類型即有bind()語句又有@ImplementedBy注解。則bind()語句優先。使用@ImplementedBy請小心,由于它為接口加入了編譯時依賴。
c. @ProvidedBy
@ProvidedBy注解用于告訴注入器。Provider類的實現是什么,比如:
@ProvidedBy(DatabaseTransactionLogProvider.class) public interface TransactionLog {void logConnectException(UnreachableException e);void logChargeResult(ChargeResult result); }這等價于bind(TransactionLog.class).toProvider(DatabaseTransactionLogProvider.class);
類似@ImplementedBy注解,假設某個類型既使用了bind()語句,又使用了@ProvidedBy注解。然后,bind()聲明優先。
版權聲明:本文博主原創文章,博客,未經同意不得轉載。
轉載于:https://www.cnblogs.com/mengfanrong/p/4829214.html
總結
以上是生活随笔為你收集整理的Google Guice结合模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP5.6.6上运行 ecshop 2
- 下一篇: 信息核心技术体系是通往信息世纪的中国门票