日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Google Guice结合模式

發布時間:2024/4/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Google Guice结合模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
于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);
而且鏈接綁定支持鏈式寫法:


public class BillingModule extends AbstractModule {@Override protected void configure() {bind(TransactionLog.class).to(DatabaseTransactionLog.class);bind(DatabaseTransactionLog.class).to(MySqlDatabaseTransactionLog.class);} }
在這樣的情況下,當請求一個TransactionLog類型對象時,注入器將返回一個MySqlDatabaseTransactionLog對象。



二、綁定注解
某些情況下你可能想為同一種類型設置多種綁定。這就能夠通過綁定注解來實現,該注解與綁定的類型用于唯一結識一個綁定,
合在一起稱為Key。演示樣例:

package example.pizza;import com.google.inject.BindingAnnotation; import java.lang.annotation.Target; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD;@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) public @interface PayPal {}
這里關鍵的是@BindingAnnotation元注解,當Guice描寫敘述到該注解時,就會把PayPal作為綁定注解。


然后在Module的configure方法中使用annotatedWith語句,例如以下:
bind(CreditCardProcessor.class).annotatedWith(PayPal.class).to(PayPalCreditCardProcessor.class);
這樣就把CreditCardProcessor映射到了PayPalCreditCardProcessor。

使用方法:


public class RealBillingService implements BillingService {@Injectpublic RealBillingService(@PayPal CreditCardProcessor processor,TransactionLog transactionLog) {...} }
另一種情況,我們能夠使用Guice已經定義好的@Named注解。比如:


public class RealBillingService implements BillingService {@Injectpublic RealBillingService(@Named("Checkout") CreditCardProcessor processor,TransactionLog transactionLog) {...} }
要綁定一詳細名稱,使用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注解。該方法的返回值類型就是被綁定的對象。

當注入器須要該類型的實例時,它就會來調用該方法。


public class BillingModule extends AbstractModule {@Overrideprotected void configure() {...}@ProvidesTransactionLog provideTransactionLog() {DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");transactionLog.setThreadPoolSize(30);return transactionLog;} }
假設在@Provides方法上有@PayPal或@Named("Checkout")綁定注解。Guice以綁定注解優先。Guice在調用@Provides方法之前會先解析該方法的依賴:


@Provides @PayPal CreditCardProcessor providePayPalCreditCardProcessor(@Named("PayPal API key") String apiKey) {PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();processor.setApiKey(apiKey);return processor; }
關于異常:
Guice不同意在@Provides方法中拋出異常。

假設有異常拋出。那么異常將會被包裝在ProvisionException對象中。

五、提供者綁定(Provider Bindings)
假設@Provides方法越來越復雜。我們可能會想把它們移到一個單獨的類中。一個提供者類實現了Provider接口。它是一個
用于提供值的簡單通用接口。


public interface Provider<T> {T get(); }
假設提供者實現類有其自己的依賴時,能夠通過在其構造方法上加入@Inject注解進行注入,以保證值安全返回。


public class DatabaseTransactionLogProvider implements Provider<TransactionLog> {private final Connection connection;@Injectpublic DatabaseTransactionLogProvider(Connection connection) {this.connection = connection;}public TransactionLog get() {DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();transactionLog.setConnection(connection);return transactionLog;} }
最后使用.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注解的構造方法,比如:


public class PayPalCreditCardProcessor implements CreditCardProcessor {private final String apiKey;@Injectpublic PayPalCreditCardProcessor(@Named("PayPal API key") String apiKey) {this.apiKey = apiKey;} }
Guice不會創建內部類實例除非它有static修飾符,由于內部類含有一個指向外問類的隱式引用,而這個隱式引用無法注入。

b. @ImplementedBy
@ImplementedBy注解于用告訴注入器某類型的缺省實現類型是什么,這與鏈接綁定非常相似。

為某一類型綁定一子類型例如以下:


@ImplementedBy(PayPalCreditCardProcessor.class) public interface CreditCardProcessor {ChargeResult charge(String amount, CreditCard creditCard)throws UnreachableException; }
@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结合模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。