我正在編寫一個庫,允許人們使用插件框架提供某些接口的實現(如果您熟悉,則爲JPF)。插件不存儲在類路徑中。該框架爲我提供了每個插件的ClassLoader,因此當請求接口「MyInterface」的名爲「MyImpl」的實現時,我可以找到正確的插件,然後使用該插件的ClassLoader加載類,從中我可以創建一個實例如果我知道關於構造函數的東西。到現在爲止還挺好。如何使用用不同的Java classloader加載的實現?
但是,現在我有一種情況,我需要調用只在該特定實現上可用的方法。因此,有兩種方法,我可以嘗試這樣做:
方法1:
// Makes sure that MyImpl has been loaded, using the custom classloader
Plugins.getClass(MyInterface.class, "MyImpl");
// This line will not compile because MyImpl is not available at build time
MyImpl foo = new MyImpl();
// If I could get this far, this line would work:
foo.methodOnlyInMyImpl();
方法2:
// This call will get an instance of MyImpl (already written and tested)
MyInterface foo = Plugins.getInstance(MyInterface.class, "MyImpl");
// Compiler error because there is no MyInterface.methodOnlyInMyImpl method.
foo.methodOnlyInMyImpl()
方法1是兩個的清潔劑,因爲它是最類似於如果類是「正常」且不能通過插件訪問的話你將如何編寫代碼。但是,沒有編譯。
選項我想出迄今:
A.使用方法2,但在使用反射做methodOnlyInMyImpl方法調用(!請,否)
B.將在構建路徑的插件類和然後使用方法1進行編譯。 (我目前最喜歡的)
C. B +安裝插件時,在類文件複製到另一個目錄是在classpath中,這樣系統類加載器可以加載它們(導致其他問題)
所以,我的問題是:
- 我是否錯過了另一個更好的想法?
- 如果我做B,我會在運行時遇到問題嗎?畢竟,使用MyImpl的類大概會使用系統類加載器加載。所以,只要它看到
MyImpl foo
,是不是會嘗試使用系統類加載器加載MyImpl,這將失敗(即使Plugins.newInstance調用將提供MyImpl的實例)?
舉例說明優點:我有接口X和Y.有一個返回Y的X.getY()方法。我有四個插件提供X實現Xa和Xb,Y實現Yc和Yd。現在,Xa和Xb都需要在內部使用實現Yc,所以這是我需要具體實現的地方。應用程序只能與X和Y交互,但插件需要特定的實現。 JPF幫助處理插件依賴關係。 –
+1 - OP正試圖忽略使用接口所暗示的合同。如果插件是唯一關心實現類的插件,那麼他/她將不得不提供編譯時訪問實現類,使用強制轉換,並處理可能的ClassCastException。 – kdgregory
不幸的是,我無法預測所有的接口。序列化(Arne),在運行時(kdgregory)和TransLoader(Carl)都需要類在當前類加載器中以某種方式可用,這在我的情況中不是這樣 - 它涉及到在運行時使用反射或放置需求classpath包含插件dirs。我選擇了後者。由於關鍵短語「由不同的類加載器加載的Java類永遠不兼容」而接受此答案。謝謝,如果我有代表,我會+1。 –