您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
CTK Plugin Framework 基本原理
 
作者昵称:一去丶二三里
   次浏览      
 2021-3-18 
 
编辑推荐:

本文主要CTK Plugin Framework是什么?它的体系结构,服务层以及它的生命周期等等相关内容。
文章来自于csdn,由火龙果Anna编辑推荐。

“CTK Plugin Framework 技术是面向 C++ 的动态模型系统。该系统允许插件之间的松散耦合,并且提供了设计良好的方式来进行功能和数据的交互。此外,它没有预先对插件施加限制,这样就可以很容易地将插件的相关部分嵌入到现有的工具包中。”

体系架构

CTK Plugin Framework 设计受到了 OSGi(Java 的动态组件系统)的极大启发,并且它提供了一种能让应用程序(动态地)由许多不同的(可重用)组件组成的开发模型。该模型允许通过服务进行通信,服务是特定于组件之间的对象。

框架的分层模型,如下图所示:

Plugins(插件):由开发人员创建的 CTK 组件;

Services Layer(服务层):通过为 C++ 对象提供一个 publish-find-bind 模型,以动态方式连接插件;

Life Cycle Layer(生命周期层):用于安装、启动、停止、更新和卸载插件的 API;

Security(安全性):处理安全方面(目前尚不可用)。

插件

Plugin 是 CTK Plugin Framework 的核心,模块化特性在这一层得到了很好的实现。那么,究竟什么是 Plugin?

Plugin:是基于 C++/Qt 的一个共享库,并包含了资源文件和元数据(metadata)。

元数据的目的在于准确描述 Plugin 的特征,除了让 CTK Plugin Framework 对 Plugin 适当地进行各种处理(例如:依赖解析)之外,还能更好的对 Plugin 进行标识,以帮助用户对 Plugin 进行理解。

元数据被定义在 MANIFEST.MF 文件中,一个典型的 MANIFEST.MF 文件如下:

Plugin-SymbolicName:HelloCTK
Plugin-ActivationPolicy:eager
Plugin-Category:Demos
Plugin-ContactAddress:https://github.com/Waleon
Plugin-Description:A plugin for say hello
Plugin-Name:HelloCTK
Plugin-Vendor:Waleon
Plugin-Version:1.0.0

虽然条目众多,但并非所有的都是必须的。这些元数据主要包含两部分:

Plugin 的标识符(必须):唯一标识一个 Plugin,由 Plugin-SymbolicName 表示。

可读的信息(可选):帮助更好地理解和使用 Plugin,不对模块化特性产生任何的影响。

对于可选信息(例如:Plugin-Name、Plugin-Vendor 等),CTK Plugin Framework 甚至会无视这些内容。

服务层

服务可以看作是服务的提供者和使用者之间的一个契约,使用者一般不关心其实现的细节,只要满足这个契约(服务应该提供什么功能、满足什么格式)就好了。使用服务的过程也包含了发现服务和达成协议的形式,也就是说,需要通过服务的标志性特征来找到对应的服务。

一个插件可以创建一个对象,并在一个或多个接口(通常是一个只有纯虚方法的 C++ 类)下使用 CTK Service Registry 注册它。其他插件可以要求 registry 列出在特定接口下注册的所有服务(对象)。一个插件甚至可以等待一个特定的服务出现,然后收到回复。

因此,一个插件可以注册一个服务,也可以获得一个服务并侦听服务的出现或消失。任意数量的插件可以在相同的接口下注册服务,并且任意数量的插件都可以得到相同的服务,如下图(publish-find-bind 模型)所示:

如果多个插件在同一个接口下注册对象,则可以通过其属性进行区分。每个服务注册都有一套标准的自定义属性,可以使用过滤器来选择感兴趣的服务。属性也可以被用于应用程序级的其他角色。

发布服务

为了让其它 Plugin 能发现这个服务,必须用上下文对其进行注册,需要用到接口名、服务对象(接口的具体实现)和一个可选的 ctkDictionary 类型的属性信息:

ctkDictionary properties;
properties.insert("name","Waleon");
properties.insert("age",18);
ctkServiceRegistration registration=context-> registerService< HelloService>(new HelloImpl(),properties);

这样,便可以得到一个 ctkServiceRegistration 对象,可以用这个对象来更新服务的属性:

registration.setProperties (newProperties);

也可以直接把这个服务移除:

registration.unregister();

注意:这个 registration 对象不能和其他 Plugin 共享,因为它和发布服务的 Plugin 的生命周期相互依存。也就是说,如果这个 Plugin 已经不存在于框架执行环境中,那么这个对象也不应该存在了—— “皮之不存,毛将焉附”。

此外,如果在删除发布的服务之前 Plugin 停止了,框架会帮助你删除这些服务。

获取服务

一旦服务被发布,它将对其他 Plugin 可用。获取服务的方式非常简单,只需要提供一个接口名即可:

ctkServiceReference reference = context-> getServiceReference <HelloService>();

注意:这里的 reference 是服务对象的间接引用,可为什么要用间接引用而不直接返回实际的服务对象呢?

实际上,这是为了将服务的使用和服务的实现进行解耦。将服务注册表作为两者的中间人,不仅能够达到跟踪和控制服务的目的,同时还可以在服务消失以后通知使用者。

这个方法的返回类型是 ctkServiceReference,它可以在 Plugin 之间互享,因为它和使用服务的 Plugin 的生命周期无关。

生命周期层

生命周期层主要用于控制 Plugin 的安装、启动、停止、更新和卸载,它可以让我们从外部管理应用或者建立能够自我管理的应用(或将两者相结合),并且给了应用本身很大的动态性。

前面已经了解了 Plugin 的概念和作用,但要真正使用 Plugin,则需要使用生命周期层的 API 来和 CTK Plugin Framework 的生命周期层进行交互。

下图为 Plugin 生命周期的状态转换图:

生命周期层的 API 主要由三个核心部分组成:ctkPluginActivator、ctkPluginContext 和 ctkPlugin。

ctkPluginActivator

ctkPluginActivator:自定义 plugin 的启动和停止。

ctkPluginActivator 是一个接口,必须由框架中的每个插件实现。框架可以根据需要创建一个插件的 ctkPluginActivator 实例。如果一个实例的?ctkPluginActivator::start()?方法成功执行,则需要保证在插件停止时调用同一个实例的?ctkPluginActivator::stop()?方法。

ctkPluginContext

ctkPluginContext:一个 plugin 在框架内的执行上下文,该上下文用于授予对其他方法的访问,以便该插件可以与框架交互。

ctkPluginContext 提供的方法允许插件:

订阅由框架发布的事件;

使用 Framework Service Registry 注册服务对象;

从 Framework Service Registry 检索 ServiceReferences;

为引用的服务获取和发布服务对象;

在框架中安装新的插件;

获取框架中安装的插件列表;

获得一个插件的 ctkPlugin 对象;

为(由框架为插件提供的)持久存储区域中为文件创建 QFile 对象。

当使用?ctkPluginActivator::start()?方法启动时,将创建一个 ctkPluginContext 对象,并将其提供给与此上下文关联的插件。当使用?ctkPluginActivator::stop()?方法停止时,相同的 ctkPluginContext 对象将被传递给与此上下文关联的插件。ctkPluginContext 对象通常用于其关联插件的私有用途,并不意味着与插件环境中的其他插件共享。

与 ctkPluginContext 对象关联的 ctkPlugin 对象称为上下文插件。

ctkPluginContext 对象只有在它的上下文插件执行时才有效;也就是说,在上下文插件处于 STARTING、STOPPING、和 ACTIVE 状态的时段内。如果随后使用 ctkPluginContext 对象,则必须抛出一个 ctkIllegalStateException 异常。当上下文插件停止后,ctkPluginContext 对象不能被重用。

Framework 是唯一能够创建 ctkPluginContext 对象的实体,并且这些对象仅在创建它们的 Framework 中有效。

ctkPlugin

ctkPlugin:Framework 中已安装的插件。

ctkPlugin 对象是定义一个已安装插件的生命周期的访问点,在插件环境中安装的每个插件都必须有一个相关的 ctkPlugin 对象。此外,插件必须有一个唯一的标识,在插件的生命周期中,这个标识不能改变(即使是在插件更新时),卸载和重新安装插件必须创建一个新的唯一标识。

插件有以下状态(状态是动态可变的,这些状态在特定条件下可以互相转换,见上图):

UNINSTALLED

INSTALLED

RESOLVED

STARTING

STOPPING

ACTIVE

要确定插件是否处于有效状态之一,可以使用 States 类型进行“或”运算。

插件只能在状态为 STARTING、ACTIVE 或 STOPPING 状态时执行代码。一个 UNINSTALLED 插件不能被设置为另一个状态,它是一个“僵尸”。

Framework 是唯一允许创建 ctkPlugin 对象的实体,并且这些对象仅在创建它们的 Framework?内有效。

   
次浏览       
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程
最新活动计划
软件架构设计方法、案例与实践 8-23[特惠]
Linux内核编程及设备驱动 8-15[北京]
Python、数据分析与机器学习 8-23[特惠]
嵌入式软件架构设计 8-22[线上]
QT应用开发 9-5[北京]
 
最新文章
.NET Core 3.0 正式公布:新特性详细解读
.NET Core部署中你不了解的框架依赖与独立部署
C# event线程安全
简析 .NET Core 构成体系
C#技术漫谈之垃圾回收机制(GC)
最新课程
.Net应用开发
C#高级开发技术
.NET 架构设计与调试优化
ASP.NET Core Web 开发
ASP.Net MVC框架原理与应用开发
更多...   
成功案例
航天科工集团子公司 DotNet企业级应用设计与开发
日照港集 .NET Framewor
神华信 .NET单元测试
台达电子 .NET程序设计与开发
神华信息 .NET单元测试
更多...