可选依赖项
有時您正在編寫的庫可能具有可選的依賴項。 例如“如果apache http客戶端在類路徑上,請使用它;否則,請使用它。 否則–退回到HttpURLConnection”。
為什么要這么做? 由于各種原因–在分發(fā)庫時,您可能不想強加較大的依賴范圍。 另一方面,更高級的庫可能會帶來性能上的好處,因此任何需要這些的人都可以包括它。 或者,您可能希望允許輕松插入某些功能的實現(xiàn),例如json序列化。 您的庫不在乎是Jackson,gson還是本機android json序列化–因此您可以使用所有這些庫提供實現(xiàn),然后選擇找到依賴項的實現(xiàn)。
實現(xiàn)此目的的一種方法是顯式指定/傳遞要使用的庫。 當庫/框架的用戶實例化其主類時,他們可以傳遞boolean useApacheClient=true或枚舉值JsonSerializer.JACKSON 。 這不是一個壞選擇,因為它迫使用戶了解他們正在使用的依賴項(并且是事實上的依賴項注入)
spring等使用的另一個選項是動態(tài)檢查類路徑上是否存在依賴項。 例如
private static final boolean apacheClientPresent = isApacheHttpClientPresent(); private static boolean isApacheHttpClientPresent() {try {Class.forName("org.apache.http.client.HttpClient");logger.info("Apache HTTP detected, using it for HTTP communication.);return true;} catch (ClassNotFoundException ex) {logger.info("Apache HTTP client not found, using HttpURLConnection.");return false;} }然后,每當您需要發(fā)出HTTP請求時(其中ApacheHttpClient和HttpURLConnectionClient是您自己的HttpClient接口的自定義實現(xiàn)):
HttpClient client = null; if (apacheClientPresent) {client = new ApacheHttpClient(); } else {client = new HttpURLConnectionClient(); }請注意,使用“ isXPresent”布爾值保護所有可能嘗試從依賴項加載類的代碼非常重要。 否則,類加載異常可能會發(fā)生。 例如在Spring,他們將Jackson依賴項包裝在MappingJackson2HttpMessageConverter
if (jackson2Present) {this.messageConverters.add(new MappingJackson2HttpMessageConverter()); }這樣,如果Jackson不存在,則不會實例化該類,也根本不會嘗試加載Jackson類。
究竟是偏愛自動檢測還是需要顯式配置要使用的基本依賴項,這是一個難題。 因為自動檢測可能會使您的庫用戶不了解該機制,并且當他們添加用于其他目的的依賴項時,它可能會被您的庫選擇,并且行為可能會更改(盡管應該這樣做,但始終存在微小的差異) 。 您當然應該記錄下來,甚至記錄消息(如上所述),但這可能不足以避免(不愉快的)意外情況。 因此,我無法回答何時使用哪種方法,應視具體情況決定。
這種方法也適用于內部依賴項–您的核心模塊可能會尋找一個更具體的模塊來使用它,否則會回退到默認值。 例如,您使用System.nano()提供了“經(jīng)過時間”的默認實現(xiàn),但是使用Android時,您最好依靠SystemClock –因此,您可能希望檢測是否存在經(jīng)過時間的android實現(xiàn)。 這看起來像邏輯耦合,因此在這種情況下,最好還是使用顯式方法。
總的來說,這是使用可選依賴項的一種很好的技術,它具有基本的后備功能。 或沒有回退的許多可能選項之一。 很高興知道您可以做到,并將其包含在問題的可能解決方案的“工具包”中。 但是您不應該總是在顯式(依賴注入)選項上使用它。
翻譯自: https://www.javacodegeeks.com/2015/06/optional-dependencies.html
總結
- 上一篇: 山宗读什么 山宗的读音
- 下一篇: 实际中进行GC调整