当前位置: 首页 > 科技观察

插件开发架构概述

时间:2023-03-17 20:24:25 科技观察

1.概述在现有的软件开发中,业务越来越复杂,代码量越来越大,依赖的人力也越来越多。为了降低系统模块的内部耦合度,降低开发难度,支持多个团队并行开发,插件化开发架构越来越流行,尤其是在桌面软件和移动应用中。对于后端开发,微服务的形式越来越流行,但据笔者了解,微服务的很多设计思路与插件式开发架构的设计理念类似。Eclipse、VisualStudio、VSCode等都是插件化开发架构的典型案例。现代软件提供了插件化的开发框架,一方面服务于产品本身的内部开发,另一方面服务于市场化。在市场上各个领域的开发者的帮助下,在某个软件(开源或商业)上开发新的领域,可以大大提高产品的市场占有率,衍生出一系列的各个领域的代理和咨询服务。2.插件开发架构要点无论使用什么语言来设计插件开发架构,都有一些共同点需要满足。2.1插件运行主体基于插件模式开发的软件一般都有一个运行主体。这个载体作为应用程序的主入口,根据各种插件的配置信息,将编译或打包的插件加载到主环境中执行。无需调整现有运行时的代码和二进制包即可开发新插件。2.2插件注入、配置和初始化2.2.1插件配置信息配置信息是插件的描述信息,可以在代码中设置,也可以通过XML文件实现。方法不同,但目的是一样的。插件名称插件版本号插件描述信息其他依赖插件列表2.2.2插件注入和初始化插件注入和初始化一般依赖于继承插件基类和实现标准插件框架中指定的接口。通过继承插件基类,实现插件注入;通过实现标准的初始化、启动、关闭等标准接口,实现插件的生命周期管理。2.2.2.1插件定义示例下面的代码是笔者参考开源软件Xfrogcn.PluginFactory所做的解释。https://gitee.com/WuYeCai/pluginfactory通过C#语言的Attribute特性来描述插件。通过实现Init、StartAsync、StopAsync标准接口来初始化、启动或关闭插件。这就是插件生命周期的管理。[Plugin(Alias="PluginA",Description="TestPlugin")]publicclassPlugin::PluginBase,ISupportInitPlugin{publicvoidInit(IPluginInitContextcontext){//自定义初始化行为}publicoverrideTaskStartAsync(IPluginContextcontext){//自定义启动行为returnbase.StartAsync(context);}publicoverrideTaskStopAsync(IPluginContextcontext){//自定义关闭行为returnbase.StopAsync(context);}}2.3.插件通信机制插件通信机制是一个通用的概念。各个插件协同完成一个功能时,是一种相互协调、相互协助的机制。交互的形式有很多种。一种是插件对外开放自己的接口,连接到服务总线上,供其他插件调用;另一种是提供消息机制,通过插件之间发送消息来进行事件处理。2.3.1基于虚拟服务总线的通信机制基于虚拟服务总线形式的通信机制,每个插件都有自己的开放接口,会注册到虚拟服务总线上,其他插件可以获取其他插件的接口服务。这里涉及的内容是面向接口的编程。2.3.2插件间的消息通信插件间的消息通信是开发者可以自定义的扩展方式,插件主体不能定义所有的消息类型和消息处理方式。因此,用户可以通过约定消息形式,自定义消息响应功能,实现插件间的通信。但是这样其实增强了插件之间的耦合度,不是特别推荐。笔者建议应用层插件尽量只依赖通用服务类插件和主要运行程序,保持业务插件独立。三、C++语言下的插件开发案例笔者曾经基于国外通用产品进行域定制。本产品基于C++/MFC开发,提供SDK包和示例工程,协助用户开发基于本产品的插件。每个插件最终都会编译成一个DLL,复制到产品的指定目录下,然后加载执行。整体格局如下图所示。支持插件注入接口通过继承插件中指定的基类并实现指定的接口,达到插件注册和初始化的效果。支持菜单和子菜单注入接口通过菜单注入接口,开发者可以在菜单中提供插件功能入口。用户可以通过这个入口启用插件。支持事件分发(已定义标准事件列表),插件可以接收事件,开发自定义事件处理器。在实际设计过程中,用户对模型、工程目录、绘图区的操作都会分发给所有的插件,类似于广播。开发者可以根据实际需要实施或不实施。提供获取当前上下文信息的接口提供访问接口,用户获取用户当前选择的模型对象、选择的目录、选择的文件等信息。提供所有业务对象的访问接口提供访问接口,可以创建和删除模型,创建和删除文件,创建和删除项目管理目录等文件。插件以DLL形式存在,在进程中加载??运行。基于插件的架构和扩展点等概念仍然令人印象深刻。开发的基石Eclipse是基??于OSGI规范开发的。4.1OSGi简介OSGi是一种基于java语言的开发和运行时模块化技术。其核心是一个框架,其中定义了应用程序的生命周期模式和服务注册表。OSGI框架定义了大量的OSGI通用服务:日志、配置管理、XML解析等通用服务。4.2OSGI总体架构4.2.1模块层模块层可以理解为开发的各种插件,通常以bundle的形式出现。一个完整的系统功能往往是由不同的模块插件相互配合完成的。模块通过约定的接口提供外部服务。每个模块的边界也被确定和封装。模块层bundle的特点:bundle是一个jar包形式的模块化物理单元,包括代码、资源文件和元数据(模块描述信息)。bundle是开发和部署OSGi应用程序的基本单元。捆绑包的核心是META-NF目录中的MANIFEST.MF文件。Bundle定义内部包的外部可见性。每个包都有一个单独的类加载器。4.2.2生命周期层管理bundle的创建和销毁。Bundle内部需要实现相关接口,配合生命周期层的工作。4.3.3服务层服务层可以理解为服务中心。每个插件通过服务层向外界发布自己可以提供的功能,并为其他插件提供服务发现方法和服务访问。4.3Eclipse插件示例Eclipse插件示例使用Eclipse自带的HelloWorld案例进行说明。插件的配置信息如下:Manifest-Version:1.0Bundle-ManifestVersion:2Bundle-Name:PluginDemoBundle-SymbolicName:PluginDemoBundle-Version:1.0.0.qualifierBundle-Activator:plugindemo.ActivatorBundle-RequiredExecutionEnvironment:JavaSE-16Automatic-Module-Name:Plugin-Package:org.osgi.framework;version="1.3.0"Bundle-ActivationPolicy:lazy一个简单的插件示例代码如下:packageplugindemo;importorg.osgi.framework.BundleActivator;importorg.osgi.framework。BundleContext;publicclassActivatorimplementsBundleActivator{@Overridepublicvoidstart(BundleContextcontext)throwsException{System.out.println("HelloWorld!!");}@Overridepublicvoidstop(BundleContextcontext)throwsException{System.out.println("GoodbyeWorld!!");}}运行EclipseOSGI模式,回车结果如下。警告:使用孵化器模块:jdk.incubator.vector,jdk.incubator.foreignHelloWorld!!osgi>22:48:00.337[Worker-0:LoadingavailableGradleversions]INFOorg.eclipse.buildship.core.internal.util.gradle.PublishedGradleVersions-upcalarytoversioninformation-date.Tryingtoread.!SESSION2021-08-3122:47:57.492-----------------------------------------------5。总结本文简要介绍了插件开发框架中的一些基本原理,以及不同语言开发的软件平台中的插件开发模式。需要注意的是,在实际的插件架构中,根据不同的产品、不同的面向领域、使用的不同的编程语言,会有很多不同的设计,需要根据具体情况进行设计。