本文首發於泊浮目的專欄: https://segmentfault.com/blog...
在ZStack博文-5.通用插件系統中,官方提出了幾個較爲經典的擴展方式。但在實際的二次開發中,這些作法未必可以徹底知足需求。今天筆者就和你們一塊兒來看一看一些常見的擴展方法。java
ZStack做爲一個開源的產品化Iaas,隨着其每一個版本的更新發布,都攜帶了極多的feature,並由其測試天團進行嚴密的測試後發佈來保證質量。同時,每一個版本也會攜帶大量的bug fix。git
若是在本身fork的ZStack中耦合了過多本身的代碼(對於Iaas的擴展或本身的業務邏輯),會致使跟不上master分支,這樣會丟失掉不少高質量feature和bug的fix。github
在ZStack源碼剖析之設計模式鑑賞——三駕馬車中,筆者提到過基於觀察者模式的ExtensionPoint。其本質是經過Java的Interface來定義一系列的實現類,並收集它們來調用,這樣它們能夠散落在各個模塊中,但在Application起來時它們卻一塊兒被Spring加載到了內存中。segmentfault
利用這種方法,咱們能夠很容易的添加本身的代碼到模塊中,但又不影響主幹代碼。設計模式
在此前提上,也能夠關注代碼中的ExtensionPointEmitter
,該組件也是參考了這樣的設計。框架
在ZStack源碼剖析之核心庫鑑賞——FlowChain一文中,咱們瞭解到Flow是ZStack的基礎設施之一,同時也容許經過XML顯示聲明的方式來聲明Flow。所以,咱們能夠經過添加本身的Flow來執行一些本身的擴展邏輯。async
基於EventFacade
fire的路徑上定義接收點。如在HostBase中,定義了HOST_DELETED_PATH
。咱們能夠選擇在本身的代碼模塊中註冊一個evft.on。用於執行本身的邏輯。ide
chain.done(new FlowDoneHandler(msg) { @Override public void handle(Map data) { casf.asyncCascadeFull(CascadeConstant.DELETION_CLEANUP_CODE, issuer, ctx, new NopeCompletion()); bus.publish(evt); HostDeletedData d = new HostDeletedData(); d.setInventory(HostInventory.valueOf(self)); d.setHostUuid(self.getUuid()); evtf.fire(HostCanonicalEvents.HOST_DELETED_PATH, d); } }).error(new FlowErrorHandler(msg) { @Override public void handle(ErrorCode errCode, Map data) { evt.setError(errf.instantiateErrorCode(SysErrors.DELETE_RESOURCE_ERROR, errCode)); bus.publish(evt); } }).start();
這裏以KvmBackend爲例,咱們先簡單的看一下這個類模塊化
public class KvmBackend extends HypervisorBackend
而HypervisorBackend
繼承了HypervisorBackend
,HypervisorBackend
繼承了SMPPrimaryStorageBase
,SMPPrimaryStorageBase
繼承了PrimaryStorageBase
。測試
咱們來看一下,KvmBackend
裏handle什麼樣的消息。
咱們能夠看到,這些Msg執行的邏輯和主存儲類型息息相關,不能以同一個PrimaryStorageBase來一律而論。所以,同一個Msg在不一樣類型的存儲、不一樣的場景下會有不同的邏輯來handle。
同理,一些ManagerImpl也能夠使用繼承進行擴展。
簡單來講,就是對基類進行擴展,覆寫那些咱們須要修改的方法。
在ZStack中,有許許多多的代碼模塊。在擴展本身的業務邏輯時,最好新建一個Module用於存放本身的代碼,對於模塊和Bean的依賴能夠按需放入(相似Plugin的形式)。並結合以上的幾個方式來進行擴展。
那麼在這個過程當中,該注意哪些事項呢?
在ZStack中,咱們能夠看到全部的Bean配置都是由ZStack.xml
管理的,
而引用xml的地方則是這裏:
所以,咱們須要注意引入的xml是否有被配置起來。
ZStack使用了Hibernate
這個ORM框架,並對映射類用XML的形式來管理。即:persistence.xml
。
須要注意的是,在DatabaseFacade的XML配置文件中,引用了該配置文件。所以對於這個文件的方式建議是覆寫(即再建立一個persistence.xml,用於引用ZStack中的表對象和本身的表對象),而不是再配置一個進行引用。由於這樣可能會影響主幹代碼。
ZStack在Test目錄下提供了大量Case。在完成本身的擴展後(照理論上來講不該該改動ZStack的源代碼),能夠嘗試在該目錄下跑全部的Case:
mvn compile && cd test && mvn test -Dtest=ZStackTest
若是都跑過了,則證實ZStack的主幹代碼可能沒有受到影響。
在本文中,筆者介紹了幾種較爲優雅的擴展方式。利用這些方法可讓咱們較爲方便的跟上主線,避免花大量精力在解決衝突上。
固然,若是你們有更好的擴展方式,也能夠在評論區補充。