本文首发于泊浮目的专栏: 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的主干代码可能没有受到影响。
在本文中,笔者介绍了几种较为优雅的扩展方式。利用这些方法可让咱们较为方便的跟上主线,避免花大量精力在解决冲突上。
固然,若是你们有更好的扩展方式,也能够在评论区补充。