Jarslink1.6.1版本特性
Jarslink 在4月初推出了新版本,增加支援Spring註解和模組多版本特性。歡迎參與開源專案,成為我們的Commiter。
註解的使用
新版本加入了註解的支援,使用者只需要在構建ModuleConfig的時候呼叫ModuleConfig.addScanPackage(String)方法即可,可以多次呼叫該方法來新增多個掃描包配置,該配置會被spring用來作為掃描包配置。
註解開啟後的一些注意事項
- 開啟註解後如果想要同時使用xml定義bean,與在普通spring專案中一樣,只需要有一個配置類(該類需要在spring的掃描路徑中),即註解為@Configuration的類,然後在該類上註解@ImportResource(“你的spring bean定義xml檔案位置”)即可,需要注意的是,由於此種方式限於spring的實現,xml中定義的bean不能依賴於註解定義的bean,而註解定義的bean則可以依賴於xml中定義的bean。
- 如過通過註解的方式定義了一個name值與xml中name值相同的bean,那麼註解定義的bean將會被xml中定義的bean所取代。
可以實現但是不推薦使用的
如果註解中依賴的bean在執行時不存在(也就是該bean是在maven中引入模組的,但是設定的scope是test或者provide等會在編譯期排除掉的),那麼此時可以在父容器中定義一個相同的bean,此時該模組A依然可以使用該bean。描述如下:
- 模組A依賴於其他jar包中的bean B;
- 打包時該jar包被剔除或者打包後被刪除;
- 父容器中提供一個與bean B相同定義的bean C;
- 模組A在父容器中執行依然可以透明的使用bean B(其實此時是bean C提供的功能)
那如果父容器和模組中同時定義了相同的bean呢?此時模組中仍然會使用本模組的bean而不會使用父容器中的bean。
如果不是必要的情況下請不要使用該功能
什麼時候應該優先使用註解載入
如果模組專案中存在這樣的情況:要引入的依賴jar包中存在spring bean的xml檔案,位置和模組專案中的一致,並且該xml檔案是不需要的,那麼此時使用xml的方式載入是無法排除該檔案的,xml檔案中的bean仍然會被載入,而使用註解的方式載入則不會存在該問題(註解其實也有,如果掃描的包名一致的話也會出現類似問題,但是正常來說包名是不會與第三方jar包一致的)。
多版本註冊功能
如何使用多版本功能
1.6.1版本支援同時註冊多個版本,該功能預設關閉,如果需要開啟那麼可以使用ModuleConfig.setNeedUnloadOldVersion(false)來開啟多版本功能。開啟後ModuleManager的register(Module)方法將可以註冊同一模組的多個版本,不開啟則後註冊的會替換新註冊的模組。
已知問題
1.6.1版本的ModuleManager預設實現存在併發問題,即使開啟多版本功能,如果某個模組在第一次註冊時同時兩個執行緒或者多個執行緒註冊,那麼此時有可能會丟失一些模組,也就是有可能會有一個或多個模組註冊失敗。該問題將在下個版本修復。
該問題只在該模組第一次註冊時會出現該問題,如果之前已經註冊過該模組之後併發註冊則不會有該問題。
示例程式碼
開啟註解
ModuleLoader moduleLoader = null;
ModuleManager moduleManager = null;
ModuleConfig config = new ModuleConfig();
//*************
//配置config的其他選項
//*************
config.addScanPackage("com.alipay");
//使用此配置載入Module將會遞迴掃描jar包中所有com.alipay目錄下的class
Module module = moduleLoader.load(config);
使用多版本註冊功能
ModuleConfig config = new ModuleConfig();
//*************
//配置config的其他選項
//*************
config.withName("demo").withVersion("1.0").withNeedUnloadOldVersion(false);
Module module = moduleLoader.load(config);
moduleManager.register(module);
config.withName("demo").withVersion("2.0").withNeedUnloadOldVersion(false);
module = moduleLoader.load(config);
moduleManager.register(module);
//此處該module的版本號為2.0,後註冊的module會被設定為預設module
module = moduleManager.find("demo");
//通過指定版本號可以獲取到之前註冊的(因為2.0版本配置了允許存在多個版本的module,所以此時1.0版本的仍然能被找到)
module = moduleManager.find("demo" , "1.0");
多版本註冊功能細節說明(實現機制)
如果檢視原始碼可以得知,needUnloadOldVersion選項只在本次註冊中有效,也就是如果當前註冊的模組配置允許存在多版本,那麼即使之前的模組是不允許存在多版本也會忽略,僅僅使用本次註冊的模組的配置,反之,如果之前模組允許多版本存在,但是當前註冊的模組不允許,那麼就會將之前的解除安裝了。當前註冊的模組不允許多版本存在時系統會如何解除安裝模組呢?如果當前註冊的模組不允許存在多版本時只會將之前的預設版本模組刪除,並不會刪除其他模組。詳情請看下列示例。
ModuleConfig config = new ModuleConfig();
//*************
//配置config的其他選項
//*************
config.withName("demo").withVersion("1.0").withNeedUnloadOldVersion(true);
Module module = moduleLoader.load(config);
moduleManager.register(module);
config.withName("demo").withVersion("2.0").withNeedUnloadOldVersion(false);
module = moduleLoader.load(config);
moduleManager.register(module);
上面這個例子最後系統將存在1.0版本和2.0版本的模組
ModuleConfig config = new ModuleConfig();
//*************
//配置config的其他選項
//*************
config.withName("demo").withVersion("1.0").withNeedUnloadOldVersion(true);
Module module = moduleLoader.load(config);
moduleManager.register(module);
config.withName("demo").withVersion("2.0").withNeedUnloadOldVersion(false);
module = moduleLoader.load(config);
moduleManager.register(module);
上面這個例子最後系統將只存在2.0版本,1.0版本在2.0版本註冊時將會被解除安裝。
ModuleConfig config = new ModuleConfig();
//*************
//配置config的其他選項
//*************
config.withName("demo").withVersion("1.0").withNeedUnloadOldVersion(true);
Module module = moduleLoader.load(config);
moduleManager.register(module);
moduleManager.activeVersion("demo", "1.1");
config.withName("demo").withVersion("2.0").withNeedUnloadOldVersion(false);
module = moduleLoader.load(config);
moduleManager.register(module);
上面這個例子最後仍然會同時存在1.0和2.0兩個版本,因為1.0版本註冊後系統將預設demo模組的預設版本切換到了一個不存在的1.1版本,當2.0版本的demo模組註冊時,雖然2.0版本配置的不允許存在多個版本存在,會將此時的預設版本解除安裝,但是此時demo模組的預設版本是一個不存在的1.1,所以並不會有實際的版本會被解除安裝,1.0也因此保留了下來。