CTK框架(八):服务追踪

news2024/9/20 21:21:11

目录

1.简介

2.实现方式

3.具体实现

3.1.新建插件PluginA​​

3.2.新建插件PluginB

4.服务追踪的优势

5.应用场景

6.总结


1.简介

        CTK服务追踪是一种机制,用于在CTK插件框架中追踪和管理插件提供的服务。当一个插件注册了一个服务到服务注册中心后,其他插件可以通过服务追踪机制来发现、获取和使用这个服务。服务追踪简化了服务的获取过程,解决了无法监听已存在服务的问题。

        如果想在B插件里使用A服务,可以专门写一个类继承ctkServiceTracker,在这个类里完成对A服务的底层操作,然后在B插件里通过这个类提供的接口来使用回收A服务。

2.实现方式

        ctkServiceTracker是CTK提供的一个类,用于追踪服务。开发者可以创建一个继承自ctkServiceTracker的类,并实现相应的接口或方法,以完成对特定服务的追踪。当服务注册或注销时,ctkServiceTracker会收到通知,并更新内部的服务引用列表。

        具体步骤为:

  • 注册服务:插件A实现了一个服务,并在其激活类中将该服务注册到服务注册中心。
  • 创建服务追踪器:插件B需要使用插件A提供的服务,因此插件B在其激活类中创建一个ctkServiceTracker的实例,用于追踪插件A提供的服务。
  • 监听服务变化:ctkServiceTracker会监听服务注册中心的变化,当插件A提供的服务可用时,它会将服务引用添加到内部列表中,并通知插件B。
  • 获取并使用服务:插件B通过ctkServiceTracker获取插件A提供的服务引用,并使用该服务。

3.具体实现

3.1.新建插件PluginA​​

CTK框架(四): 插件编写-CSDN博客

 在CTK框架(四): 插件编写里面介绍了PluginA​​的编写,不清楚的可以去翻翻看。

3.2.新建插件PluginB

        因为真正使用到A服务的地方就是B插件的实现类里,所以通过构造函数把tracker给传进去。这里的tracker是在激活类里new的,因为context是从实现类里传进来的,根据这个思路也可把context传到B的实现类里,再在实现类里new出tracker。

        ctkServiceTracker里主要实现以下三个接口,注意ctkServiceTracker是一个模板类,需要指明主要追踪的服务类名。

template<class S = QObject*, class T = S>
class ctkServiceTracker : protected ctkServiceTrackerCustomizer<T>
{
    //...
protected:
    virtual T addingService(const ctkServiceReference& reference) = 0;
    virtual void modifiedService(const ctkServiceReference& reference, T service) = 0;
    virtual void removedService(const ctkServiceReference& reference, T service) = 0;
    
    //...
};  

插件结构

PluginBService:接口类
PluginBImpl:实现类
PluginBActivator:激活类
ServiceTracker:追踪类

接口类:​​PluginBService​​

#ifndef PLUGINB_SERVICE_H
#define PLUGINB_SERVICE_H

#include <QtPlugin>

class PluginBService
{
public:
    virtual ~PluginBService() {}
    virtual void B_Func() = 0;
};

#define PluginBService_iid "org.commontk.service.demos.PluginBService"
Q_DECLARE_INTERFACE(PluginBService, PluginBService_iid)
//此宏将当前这个接口类声明为接口,后面的一长串就是这个接口的唯一标识。
#endif // PLUGINB_SERVICE_H

实现类:​​PluginBImpl​​

#ifndef PLUGINB_IMPL_H
#define PLUGINB_IMPL_H

#include "PluginBService.h"
#include <QObject>

class ServiceTracker;

class PluginBImpl : public QObject, public PluginBService
{
    Q_OBJECT
    Q_INTERFACES(PluginBService)
    /*
    此宏与Q_DECLARE_INTERFACE宏配合使用。
    Q_DECLARE_INTERFACE:声明一个接口类
    Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类
    */

public:
    PluginBImpl(ServiceTracker *tracker);
    void B_Func() Q_DECL_OVERRIDE;

private:
    ServiceTracker *m_pTracker;
};

#endif // PLUGINB_IMPL_H
#include "PluginBImpl.h"
#include <QtDebug>
#include "../PluginA/PluginAService.h"
#include "ServiceTracker.h"

PluginBImpl::PluginBImpl(ServiceTracker *tracker)
    : m_pTracker(tracker)
{
    QString currPath = QCoreApplication::applicationDirPath();
    qDebug() << "PluginB current path : " << currPath;
}

void PluginBImpl::B_Func()
{
    QString currPath = QCoreApplication::applicationDirPath();
    qDebug() << "PluginB current path1 : " << currPath;

    PluginAService* service = static_cast<PluginAService*>(m_pTracker->getService());
    if (service != Q_NULLPTR) {
        service->A_Func();
    }else {
        qDebug()<<"get AbsPrintServer from tracker failed";
    }
}

激活类:​​PluginBActivator​​

#ifndef PLUGINBACTIVATOR_H
#define PLUGINBACTIVATOR_H
#include <QObject>
#include "ctkPluginActivator.h"
#include "PluginBService.h"

class PluginBImpl;
class ServiceTracker;

class PluginBActivator : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "PLUGINB")
    //向Qt的插件框架声明,希望将xxx插件放入到框架中。

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);

private:
    PluginBImpl *m_pPlugin;
    ServiceTracker* m_pTracker;
    ctkServiceRegistration m_registration;
};
#endif // PLUGINBACTIVATOR_H
#include "PluginBActivator.h"
#include "PluginBImpl.h"
#include "ServiceTracker.h"
#include <QDebug>

void PluginBActivator::start(ctkPluginContext* context)
{
    // 开启服务跟踪器
    m_pTracker = new ServiceTracker(context);
    m_pTracker->open();

    m_pPlugin = new PluginBImpl(m_pTracker);
    m_registration = context->registerService<PluginBService>(m_pPlugin);
}

void PluginBActivator::stop(ctkPluginContext* context)
{
    Q_UNUSED(context)
    //Q_UNUSED,如果一个函数的有些参数没有用到、某些变量只声明不使用,但是又不想编译器、编辑器报警报,其他没有什么实际性作用

    // 注销服务
    m_registration.unregister();

    // 关闭服务跟踪器
    m_pTracker->close();

    delete m_pPlugin;
    m_pPlugin = Q_NULLPTR;
}

追踪类:​​ServiceTracker​​

#ifndef SERVICETRACKER_H
#define SERVICETRACKER_H
#include <ctkPluginContext.h>
#include <ctkServiceTracker.h>
#include "../PluginA/PluginAService.h"

class ServiceTracker : public ctkServiceTracker<PluginAService *>
{
public:
    ServiceTracker(ctkPluginContext* context) : ctkServiceTracker<PluginAService *>(context) {}
    ~ServiceTracker() {}

protected:
    // 在 Service 注册时访问
    PluginAService* addingService(const ctkServiceReference& reference) Q_DECL_OVERRIDE {
        qDebug() << "Adding service:" << reference.getPlugin()->getSymbolicName();
        PluginAService* service = (PluginAService*)(ctkServiceTracker::addingService(reference));
        return service;
    }

    void modifiedService(const ctkServiceReference& reference, PluginAService* service) Q_DECL_OVERRIDE {
        qDebug() << "Modified service:" << reference.getPlugin()->getSymbolicName();
        ctkServiceTracker::modifiedService(reference, service);
    }

    void removedService(const ctkServiceReference& reference, PluginAService* service) Q_DECL_OVERRIDE {
        qDebug() << "Removed service:" << reference.getPlugin()->getSymbolicName();
        ctkServiceTracker::removedService(reference, service);
    }
};
#endif // SERVICETRACKER_H

测试

我们在B插件的实现类中的​​B_Func()​​接口中,通过服务追踪调用了服务A的接口A_Func(),如下:

启用插件,然后调用B_Func(),修改main.cpp,添加如下代码段

//启用A插件
try {
    // 安装插件
    QString PluginA_dir = "D:/openCode/ctkcreator/bin/qmake/debug/plugins/PluginA.dll";
    QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(PluginA_dir));
    qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    // 启动插件
    plugin->start(ctkPlugin::START_TRANSIENT);
    qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
} catch (const ctkPluginException &e) {
    qDebug() << QString("Failed install or run plugin: ") << e.what();
    return -2;
}

//启用B插件
try {
    // 安装插件
    QString PluginB_dir = "D:/openCode/ctkcreator/bin/qmake/debug/plugins/PluginB.dll";
    QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(PluginB_dir));
    qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
    // 启动插件
    plugin->start(ctkPlugin::START_TRANSIENT);
    qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
} catch (const ctkPluginException &e) {
    qDebug() << QString("Failed install or run plugin: ") << e.what();
    return -2;
}

// 获取服务引用
ctkServiceReference reference = pluginContext->getServiceReference<PluginBService>();
if (reference) {
    // 获取指定 ctkServiceReference 引用的服务对象
    PluginBService* service = pluginContext->getService<PluginBService>(reference);
    if (service != Q_NULLPTR) {
        // 调用服务
        service->B_Func();
    }
}

输出:

Adding service: "PluginA"
PluginB current path :  "D:/openCode/ctkcreator/bin/qmake/debug"
PluginB current path1 :  "D:/openCode/ctkcreator/bin/qmake/debug"
A_Func()

可以看到在插件B中成功通过服务追踪,调用了服务A的接口A_Func()

4.服务追踪的优势

1)简化服务获取:通过服务追踪,插件可以更容易地获取其他插件提供的服务,无需编写复杂的代码来监听服务变化。

2)提高系统灵活性:服务追踪使得插件之间的依赖关系更加灵活,插件可以在运行时动态地发现和使用其他插件提供的服务。

3)支持动态服务:由于服务追踪可以监听服务注册中心的变化,因此它支持动态服务的注册和注销,使得系统更加健壮和灵活。

5.应用场景

CTK服务追踪在基于CTK插件框架的应用程序中具有广泛的应用场景,例如:

  • 日志服务:一个插件提供日志服务,其他插件通过服务追踪机制来获取和使用这个日志服务来记录日志信息。
  • 认证服务:一个插件实现用户认证功能,其他插件通过服务追踪机制来获取和使用这个认证服务来进行用户认证。
  • 数据共享:插件之间通过服务追踪机制来共享数据或资源,实现数据的互通和共享。

6.总结

        CTK服务追踪是CTK插件框架中一个重要的功能,它允许开发者追踪和管理插件提供的服务。通过服务追踪机制,插件可以更容易地获取和使用其他插件提供的服务,从而提高系统的灵活性和可扩展性。在实际开发中,开发者可以根据需要创建自定义的服务追踪器来实现对特定服务的追踪和管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2122833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SCADA|KingIOServer数据存入KingHistorian的过程记录

哈喽,你好啊,我是雷工! KingIOServer是采集数据的软件,KingHistorian是工业数据库; 最近用到KingIOServer采集到的数据存入到KingHistorian工业库,然后KingFusion再连接KingHistorian获取历史数据并曲线展示的应用功能; 以下为测试笔记; 01 软件安装 KingIOServer软…

动态代理IP池设计:打造高效网络工具

在互联网飞速发展的今天&#xff0c;动态代理IP池成为了网络世界中的一大法宝。无论是数据采集、网络营销还是电商运营&#xff0c;动态代理IP池都能提供极大的便利。今天&#xff0c;我们来深入探讨一下如何设计一个高效的动态代理IP池。 什么是动态代理IP池&#xff1f; 动…

高性能多目标进化优化算法求解DTLZ1-DTLZ9,MATLAB代码

DTLZ&#xff08;Deb-Thiele-Laumanns-Zitzler&#xff09;测试函数系列是多目标优化领域中一组广泛使用的基准测试问题。这些测试问题由Kalyanmoy Deb、Lothar Thiele、Marco Laumanns和Eckart Zitzler于2002年提出&#xff0c;旨在评估和比较多目标优化算法的性能。以下是DTL…

HTML5+CSS+JS制作中秋佳节页面

HTML5CSSJS制作中秋佳节页面 中秋节&#xff0c;是中国民间的传统节日。每年农历八月十五庆祝。 在中秋节这一天&#xff0c;人们会通过各种方式庆祝&#xff0c;其中最重要的活动之一就是赏月。家人团聚在一起&#xff0c;共同欣赏明亮的月亮。同时&#xff0c;吃月饼也是中秋…

【Go】-Gin框架

目录 Gin框架简介 简单示例 Gin渲染 HTML渲染 自定义模板函数 静态文件处理 使用模板继承 JSON渲染和XML渲染 获取参数 获取querystring参数 获取form参数 获取Path参数 参数绑定 文件上传 单个文件上传 参数 多个文件上传 重定向 HTTP重定向 路由重定向 …

【Tourism】Xianyang

文章目录 1、陕西省咸阳市2、清渭楼3、古渡廊桥4、古渡遗址博物馆5、文庙6、窦家BingBing面7、凤凰台8、安国寺9、福园巷子10、参考 1、陕西省咸阳市 咸阳市&#xff0c;陕西省辖地级市&#xff0c;地处陕西省关中平原中部&#xff0c;是中国大地原点所在地&#xff0c;其境东…

iPhone 16系列发布:硬件升级但创新乏力?iPhone还值得入手吗?

2024年苹果发布会如约而至&#xff0c;重磅推出了iPhone 16系列。然而&#xff0c;发布会结束后&#xff0c;许多科技评论员和用户不禁质疑&#xff1a;苹果的创新精神是否逐渐消退&#xff1f;从发布会的内容来看&#xff0c;iPhone 16在设计、性能上有所提升&#xff0c;但和…

软件测试之单元测试与unittest框架详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 单元测试的定义 1. 什么是单元测试&#xff1f; 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&…

快来看,图书《人工智能怎么学》电子书上线啦!

图书《人工智能怎么学》出版后&#xff0c;受到了读者们的喜爱&#xff0c;被读者们亲切的称为“人工智能宝典”。不少读者留言说书籍具有很强的检索功能&#xff0c;想学人工智能的某些知识时&#xff0c;通过查阅此书&#xff0c;很方便就能够找到相关的著名教材、精品课程、…

【网易低代码】第3课,页面表格删除功能

你好&#xff01; 这是一个新课程 CodeWave网易低代码 通过自然语言交互式智能编程&#xff0c;同时利用机器学 习&#xff0c;帮助低代码开发者进一步降低使用门槛、提高应用开发效率 【网易低代码】第3课&#xff0c;页面表格删除功能 1.拖拽组件link链接到表格中&#xff0c…

航空航天混合动力(2)电动飞机发展中的电气连接挑战

航空航天混合动力(2)电动飞机发展中的电气连接挑战 1.概述2.更高的电压(千伏)和功率(兆瓦)2.缓解局部放电/电晕效应3.提高可靠性,更恶劣的环境,频繁的维护和检查,冲击和振动4.减重5.抗电弧跟踪和液压油阻力6.严格的可燃性,毒性和烟雾要求7.海拔和气压的影响8.工作温度范围…

RSA 非对称加密工具类

目录 Maven依赖RSA 非对称加密工具类效果图 Maven依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.31</version></dependency>RSA 非对称加密工具类 import cn.hutool.core.c…

100个候选人,没一个能讲明白什么是自动化框架?

什么是自动化测试框架 01 什么是框架 框架是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及构件实例间交互的方法。它规定了应用的体系结构&#xff0c;阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程&#xff0c;表现为一组抽象类以及其实例之间…

AntSKPro AI知识库一体机:深度解析RTX 4060 8G与RTX 3060 12G在大模型处理中的性能优劣势

1. 架构与性能 RTX 4060 8G&#xff1a;基于NVIDIA的较新架构&#xff0c;可能提供更高的计算效率和更先进的功能&#xff0c;如更高效的光线追踪和AI处理能力。RTX 3060 12G&#xff1a;虽然是基于较早的架构&#xff0c;但拥有更大的显存容量&#xff0c;对于处理大型数据集…

【828华为云征文|工欲善其事必先利其器:华为云Flexus X实例 一键部署宝塔面板】

文章目录 Flexus云服务器X实例介绍华为云的神秘新武器Flexus云服务器X实例的独门绝技Flexus云服务器X实例&#xff1a;哪里有需要&#xff0c;哪里就有我 一键部署宝塔面板Flexus云服务器X 购买及登录使用部署宝塔面板什么是宝塔面板一键安装宝塔面板如何放行13012端口&#xf…

Qt进程间通信,不推荐使用QSharedMemory和QLocalSocket

1、据网友说QLocalSocket有问题&#xff0c;共享内存QSharedMemory也有&#xff0c;多线程问题&#xff0c;不灵活&#xff0c;丢数据都有&#xff0c;而且还占资源。后来换成了zmqprotobuf。 2、zmq ZMQ(zeromq)被称为史上最快的“消息队列”,它处于会话层之上,应用层之下,使用…

ElasticSearch的DSL查询④(DSL查询、RestClient的DSL查询)

目录 一、DSL查询 1.1 快熟入门 1.2 叶子查询 1.2.1 全文检索查询 1&#xff09;match查询 2&#xff09;multi_match查询 1.2.2 精确查询 1&#xff09;term查询 2&#xff09;range查询 3&#xff09;ids查询 1.3 复合查询 1.3.1 bool查询 1.3.2 算分函数查询 …

9月10号的学习

//界面1 头文件 signals://界面1的自定义信号void my_signal(); private slots:void on_pushButton_2_clicked();void on_pushButton_clicked(); //界面1 .cpp文件 void Widget::on_pushButton_2_clicked() {QMessageBox msg(QMessageBox::Warning,"警告","是否…

Linux学习-ELK(一)

配置三台elasticsearch服务器 安装包 elasticsearch.j2 报错 #---执行rsync命令报以下错误 [rootes1 ~]# rsync -av /etc/hosts 192.168.29.172:/etc/hosts root192.168.29.172s password: bash: rsync: 未找到命令 rsync: connection unexpectedly closed (0 bytes receive…

【Unity面经】性能优化篇

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…