微内核架构模式
写本篇主要是用来后面写一篇可扩展性软件设计打好基础。
微内核定义:
微内核是内核的一种精简形式。将通常与内核集成在一起的系统服务层被分离出来,变成可以根据需求加入选件 这样就可提供更好的可扩展性和更加有效的应用环境。使用微内核设计,对系统进行升级,只要用新模块替换旧模块,不需要改变整个操作系统。
微内核架构模式来源于操作系统,本文主要讲解微内核模式在应用软件中的如何实现。
微内核架构模式组成:
一般由下面几个部分组成:微内核、内核、扩展服务(我更喜欢叫做扩展插件)。
内核由几个最基本服务组成,微内核完成加载内核里所有的基本服务。
内核基本服务在应用软件中通常是指那些与业务无关的服务,如资源加载服务等。
整个系统就是由微内核、内核(即几个基本服务,广义来讲我称它为插件,所以是容器自带的几个默认插件,能提供基本服务)、扩展服务(广义来讲我称它为插件,只不过是业务系统写的插件让微内核扩展进来的)。
抽象来讲就是由微内核和许多插件组成。如下图
微内核做了什么事?
微内核主要负责插件的生命周期管理,插件的加载,替换,卸载。
对于加载,替换,卸载都有两种方式,静态与动态。动态的更加复杂。
插件是什么?
插件一般由以下几部分组成:插件暴露的接口(我一般称为叫API),插件内部实现,插件扩展点以及插件配置。插件扩展点我一般设计为SPI,因为它符合(java中的API/SPI的概念,关于API/SPI请参考API/SPI可扩展设计原则)。
整个插件组成示意图如下
以读数据插件为例,读数据插件主要提供读数据服务,插件暴露接口叫做DataReadAPI。假设是网站前台系统。插件的内部实现是先读缓存,后读数据库。把读缓存与读数据库抽象出来一个接口叫DataReadSPI。在内部实现只要读取插件扩展点getExtensions(DataReadSPI.java)得到一个DataReadSPI列表,顺序执行即可(顺序执行必须是前面执行的结果为空时再往下执行)。
如果实现了扩展点有两个:如图中的DataReadCacheImpl和DataReadDBImpl,那这两个扩展点在插件配置时把缓存配在前面。于是就形成先读缓存,如果缓存读不到就读数据。
看一下代码比较容易明白
微内核框架端public interface Plugin { void init(PluginContext pluginContext); <T> List<T> getExtension(Class<T> extensionClassName);}public class PluginManager { public static <T extends Plugin> T getPlugin() { //返回插件 return null; } }public interface DataReadAPI extends Plugin { Object read(String key);}public interface DataReadSPI { Object read(String key);}public class DefaultDataReadImpl extends AbstractPlugin implements DataReadAPI { @Override public Object read(String key) { List<DataReadSPI> extensions = getExtension(DataReadSPI.class); for (DataReadSPI extension : extensions) { Object result = extension.read(key); if (result != null) { return result; } } return null; }}
客户端或叫应用端代码及配置,即微内核框架的使用端public class DataReadCacheImpl implements DataReadSPI { @Override public Object read(String key) { return null; }}public class DataReadDBImpl implements DataReadSPI { @Override public Object read(String key) { return null; }}插件扩展的配置文件<plugins><plugin id="dataReadAPIPluginID"><extensions><extension interfaceClassName="com.liyh.devine.web.spi.DataReadSPI"><implements><implment beanName="DataReadCacheImpl" /><implment beanName="DataReadDBImpl" /></implements></extension></extensions></plugin></plugins>业务代码public class Client { public static void main(String[] args) { DataReadAPI dataReadAPI = PluginManager.getPlugin("dataReadAPI"); Object result = dataReadAPI.read("key"); System.out.println(result); }}