我想了解Java的ServiceLoader
的概念,工作機制和具體的使用案例,但找到官方documentation太抽象和混亂。Java服務加載器說明
首先,文件概述了服務和服務提供商。 服務是一組打包在jar文件(API庫)中的接口和抽象類。服務提供者是一組實現或擴展API的類,它們封裝在一個獨特的jar文件(提供程序庫)中。
到目前爲止好,但隨後文檔變得混亂。
爲了加載,服務由單一類型表示,即單個接口或抽象類。 (可以使用具體類,但不建議這樣做。)給定服務的提供者包含一個或多個具體類,這些類可以擴展此服務類型,並提供特定於提供者的數據和代碼。提供者類通常不是整個提供者本身,而是包含足夠信息的代理,以確定提供者是否能夠滿足特定請求以及可以按需創建實際提供者的代碼。提供者類的細節往往是高度服務特定的;沒有一個類或接口可以統一它們,所以這裏沒有定義這種類型。該工具強制執行的唯一要求是提供程序類必須具有零參數構造函數,以便在加載期間可以對其進行實例化。
那麼究竟是服務類型和Provider類?我得到的印象是,服務類型是API庫中的facade,提供者類是提供程序庫中實現此Facade接口的實例,實際上這個類是ServiceLoader
加載的。它是否正確?但對我來說,它仍然沒有什麼意義,所有的組件如何連接在一起。
提供者類是一個代理,它決定提供者是否能夠滿足特定請求以及可以按需創建實際提供者的代碼?沒有統一的類型可以定義在哪裏?基本上所有這一段都是令人困惑的,我希望通過一個具體的例子來聽取更多可理解的解釋。
然後約供應商配置文件 ...
服務提供商通過將供應商的配置文件中的資源目錄META-INF /服務標識。該文件的名稱是服務類型的完全限定二進制名稱。該文件包含具體提供程序類的完全限定二進制名稱列表,每行一個 ...
命名特定提供程序的配置文件不需要與提供程序本身位於同一個jar文件或其他分發單元中。提供者必須可以從最初查詢的相同類加載器訪問以查找配置文件;請注意,這不一定是實際加載文件的類加載器。
這是否意味着服務類型爲org.foo的API。BarServiceType,類路徑中必須存在提供者jar,其中包含實現此類型的類和META-INF/services/org.foo.BarServiceType
命名的提供程序配置文件列出了此提供程序類,它們都可以通過相同的Classloader
訪問,其中哪些代碼可以加載ServiceLoader
以在API上查找和綁定提供程序?
從類加載器的角度來看,可訪問意味着提供程序配置文件和提供程序庫可以在程序包之外提供,位於層次結構的上方,即來自容器或其他中間件。
提供程序配置文件列出提供程序類,並可能捆綁在提供程序包中(爲什麼它會列出多個類,如果捆綁?)或來自外部。但是更常見的方法是:在提供者中提供配置文件,還是從API庫本身提供列出一組受支持的提供者的文件?或者後者是一種誤解?
最後約ServiceLoader
凡ServiceLoader
實際實例化,並呼籲加載服務提供商?這是否發生在由API庫提供的工廠方法中?例如,LoggingFactory.getLogger(clazz)
的SLF4J內部委託給ServiceLoader
,它使用反射來讀取提供者配置文件並加載服務?
服務加載機制如何處理情況,有多個提供者的配置文件存在,還是存在提供程序配置文件條目,但不包含類本身?
除了日誌框架之外還有其他一些ServiceLoader
的具體用例嗎?它在多大程度上被廣泛使用在流行的框架之下,如Java EE,Spring and Hibernate?有什麼替代服務加載機制與鬆散耦合的API提供程序綁定,或者有?
真的很有幫助。但我仍然發現一件令人困惑的事情:「服務提供者類通常是一個輕量級類,它允許應用程序訪問更重的類,當且僅當應用程序決定需要它時」。這是否僅僅意味着它加載的類是完整API的外觀,還是'proxy'在這裏有更多的動態行爲 –
它既不是façade也不是代理。這有點像工廠。例如,[XPathFactory](https://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html)不是[XPath]的外觀或代理(https:/ /docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPath.html)實例;它是獲取XPath實例的手段。 – VGR