写本篇主要是用来后面写一篇可扩展性软件设计打好基础。
[b]微内核定义:[/b]
微内核是内核的一种精简形式。将通常与内核集成在一起的系统服务层被分离出来,变成可以根据需求加入选件 这样就可提供更好的可扩展性和更加有效的应用环境。使用微内核设计,对系统进行升级,只要用新模块替换旧模块,不需要改变整个操作系统。
微内核架构模式来源于操作系统,本文主要讲解微内核模式在应用软件中的如何实现。
[b]微内核架构模式组成:[/b]
一般由下面几个部分组成:微内核、内核、扩展服务(我更喜欢叫做扩展插件)。
内核由几个最基本服务组成,微内核完成加载内核里所有的基本服务。
内核基本服务在应用软件中通常是指那些与业务无关的服务,如资源加载服务等。
整个系统就是由微内核、内核(即几个基本服务,广义来讲我称它为插件,所以是容器自带的几个默认插件,能提供基本服务)、扩展服务(广义来讲我称它为插件,只不过是业务系统写的插件让微内核扩展进来的)。
抽象来讲就是由微内核和许多插件组成。如下图
[img]http://dl.iteye.com/upload/attachment/0077/5298/6c28c045-2b7d-3af1-92c8-3b5bf6b53899.jpg[/img]
微内核做了什么事?
微内核主要负责插件的生命周期管理,插件的加载,替换,卸载。
对于加载,替换,卸载都有两种方式,静态与动态。动态的更加复杂。
插件是什么?
插件一般由以下几部分组成:插件暴露的接口(我一般称为叫API),插件内部实现,插件扩展点以及插件配置。插件扩展点我一般设计为SPI,因为它符合(java中的API/SPI的概念,关于API/SPI请参考[url=http://stan001140.iteye.com/blog/1743874]API/SPI可扩展设计原则[/url])。
整个插件组成示意图如下
[img]http://dl.iteye.com/upload/attachment/0077/5300/36f6778f-3caf-36e4-8534-17bddc9e63b2.jpg[/img]
以读数据插件为例,读数据插件主要提供读数据服务,插件暴露接口叫做DataReadAPI。假设是网站前台系统。插件的内部实现是先读缓存,后读数据库。把读缓存与读数据库抽象出来一个接口叫DataReadSPI。在内部实现只要读取插件扩展点getExtensions(DataReadSPI.java)得到一个DataReadSPI列表,顺序执行即可(顺序执行必须是前面执行的结果为空时再往下执行)。
如果实现了扩展点有两个:如图中的DataReadCacheImpl和DataReadDBImpl,那这两个扩展点在插件配置时把缓存配在前面。于是就形成先读缓存,如果缓存读不到就读数据。
[b]看一下代码比较容易明白[/b]
微内核框架端
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);
}
}
[b]解释一下:[/b]
客户端使用框架提供的插件服务,即插件暴露的API--->DataReadAPI,框架满足不了客户端的功能可以实现自己的扩展,如DataReadCacheImpl,DataReadDBImpl。插件一般会提供默认的实现,只不过本例默认实现为空,只是简单调用一下扩展点的功能就返回了。
这里比较巧, API与SPI是一样的,其实一般SPI是API实现过程中开放的扩展点,一般可以比较小。比如RenderAPI,用于渲染的API,它的SPI可能就是一个PullToolFacotry,PullToolFacotry主要返回PullTool。当应用使用微内核框架的Render插件时,可以扩展自己的PullTool返回给框架。
[b]总结[/b]
微内核模式的核以是插件管理与及协调插件之间的调用。插件是可以整个被替换,插件本身是一个很大粒度的扩展点。同时插件可以提供自己的小粒度扩展点。这样整个系统就是由一个微内核加很多插件组成一个具备很强的扩展性的系统。