插件框架PF4J-从理论到实践

news2024/11/27 16:30:54

PF4J:Plugin Framework for Java

目录

是什么?

不是什么?

特点

组件

主要类

流程概述

spring-pf4j

思考

功能模块化


我对pf4j的封装和使用demo

GitHub - chlInGithub/pf4jDemo: pf4j demo 

是什么?

开源轻量级的插件框架。通过插件形式对系统功能进行个性化扩展。插件需要实现扩展点,扩展点由系统进行定义。

不是什么?

功能模块化加载框架。虽然介绍中描述pf4j可以将庞大的系统转化为模块系统,但依据我的实践来看,仅仅依赖pf4j只能动态加载扩展,无法动态加载完整的功能模块。

特点

  • 开源轻量级的插件框架
  • 简单的标记扩展点,使用interface ExtensionPoint即可将接口和抽象类定义为扩展点
  • 简单的标记扩展,使用@Extension即可定义一个扩展

组件

插件  等同于 由 扩展点、扩展、生命周期行为 构成的一个集合。 

Plugin所有插件的基类。每一个插件均由单独的classloader进行加载,避免冲突。
PluginManager对插件进行切面化管理,如loading, starting, stopping。已提供3中实现,JarPluginManager, ZipPluginManager, DefaultPluginManager(jar_zip)。也可自行实现个性化pluginManager,需要实现AbstractPluginManager。
PluginLoader加载插件需要的所有信息,如class
ExtensionPoint扩展点
Extension扩展,即扩展点的实现

主要类 

PluginManagerpf4j通过PluginManager向外提供plugin管理能力,如生命周期控制、获取扩展实例
PluginWrapperplugin的包装类
ManifestPluginDescriptorFinder从(支持jar\zip\目录)manifest文件读取插件信息,如Plugin-Id(用于避免重复load)、Plugin-Version、Plugin-Class
PluginLoader

用于load plugin需要的所有信息,每个pluginPath对应一个pluginLoader,为每个plugin提供独立的classloader。

如JarPluginLoader

PluginClassLoader自定义的classLoader,修改了loadClass的逻辑。每个plugin对应一个PluginClassLoader实例
PluginState插件生命周期期间的各种状态
DependencyResolver插件间依赖关系分解器。一系列插件之间构建依赖图,唯一入口resolve可以返回依赖分解结果,如插件之间是否存在循环依赖、能否找到依赖的插件、插件依赖版本是否正确等。
LegacyExtensionFinder读取plugin包中META-INF/extensions.idx文件,获取扩展信息和实例。

生命周期概述

加载插件过程MF文件中插件描述-->插件独立classLoader-->插件间依赖解析-->插件已解析状态
开始插件过程加载Plugin实现并生成实例-->调用Plugin.start()-->插件已开始状态
获取某个扩展点实现类的实例
停止插件插件状态变为停止
卸载插件从集合中清除,关闭classLoader

spring-pf4j

将扩展注册为spring ioc bean

思考

如何支持租户场景

pf4j非线程安全,允许不同租户维护各自插件的场景,需要在pf4j基础上再包裹一层,一方面增加线程安全,一方面维护租户与插件、扩展的关系。

需要以一种路径规范存放插件jar,如下图:

如何支持插件依赖的jar

  • 方式1:系统列举出支持的jar集合,插件依赖其中的jar。在demo中已体现该场景,插件正常运行。

如图为插件的pom依赖,插件jar中不包含依赖的任何jars。

插件jar放到上图的租户路径下,在系统中运行Pf4jTest.main,插件扩展运行正常。因为系统的classpath中包含common-lang jar,所以classloader可以找到common-lang中class。

扩展运行结果如下,可以清晰看出,两个插件的classloader是独立的。

  • 方式2:插件jar内部包含依赖的jars
    • 方式2.1:jdk的classloader不支持嵌套jar,需参考spring LaunchedURLClassLoader或JarClassLoader(http://www.jdotsoft.com/JarClassLoader.php)。在不改变pf4j源码情况下,无法实现该方案,因为pf4j使用URLClassLoader。
    • 方式2.2:解压插件jar-->pf4j加载插件jar-->修改生成的classloader的扫描范围,添加依赖jars路径-->启动插件jar
  • 方式3:系统根据插件jar的(maven)依赖去下载依赖的jar

功能模块化

基本能力:系统功能进行模块划分,模块可动态加载和卸载,模块独立且隔离,模块间资源不产生冲突。
设计思路:独立的classloader(修改加载class的顺序,自有范围-->双亲委派)、springcontext、生命周期管理
 

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

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

相关文章

三相三线、三相四线、三相五线制区别

三相三线、三相四线、三相五线制区别 1、三相三线2、三相四线3、三相五线4、三相三线和三相四线的区别5、三相四线和三相五线的区别 1、三相三线 由A、B、C这3根相线俗称火线组成,没有布置零线N和接地线PE,这种布线方式常见于交流380V的上一级10KV的系统…

Maven安装教程

maven环境配置(点击此电脑右键属性): 点击高级系统设置,点击环境变量: 开始配置环境变量(点击系统变量,新建按钮): 新建系统变量:MAVEN_HOMED:\maven\apac…

vueX学习看这篇就够了

vuex就是为了实现全局状态管理 vuex有哪些东西? state【状态】getter【可以认为是 store 的计算属性,不会修改状态】mutation【唯一修改state的方法,不支持异步】action【不能直接修改state,通过触发mutation修改状态,支持异步】…

GPT聊天功能,逐字返回数据

目录 前言一、前端二、后端1.接收前端请求的api如下是继续向其他接口请求的api如下是直接返回前端数据的api甚至可以返回图片 2.模拟GPT的接口 前言 我们在和GPT交流的时候发现GPT总是逐字的显示,因为GPT是一种基于神经网络的自然语言处理模型,它的训练…

王道考研计算机网络第一章知识点汇总

以上内容为1.1概念与功能的重点知识点 以下为1.2组成与分类: P2P模式下每台主机既可以是客户也可以是服务器,主机越多资源分享速度越快。 1.3标准化工作及相关组织 1.4性能指标 带宽只是指的是从主机内部往传输链路上投送数据的最大能力(从入口端放入数…

棱镜七彩中标浦发银行项目 助力金融行业开源治理

近日,棱镜七彩凭借出色的研发实力和优秀的产品服务能力在众多竞标企业中脱颖而出,成功中标上海浦东发展银行创新实验室“开源治理扫描工具信创改造课题”项目。棱镜七彩将为浦发银行在开源软件治理、软件安全可靠性等方面提供全方位支持。 在数字经济发…

odoo from 表单自定义按钮 执行JS代码 并调用websoket

业务场景: 集成串口读取RFID数据。由于串口是需要在客户端本地电脑执行才可以拿到数据 但是系统 部署在服务器 不能直接调用串口。 解决方案: 利用websoket通信 调用串口 传输 读取到的串口数据,解决服务器与本地之间的通信 本场景是基于odo…

深度解析:2023年软件测试的10个新趋势和挑战

随着技术的飞速发展,软件测试的角色和责任也在经历重大转变。我们在2023年目前所面临的一些新趋势和挑战值得所有从业人员关注。以下是这些主要趋势和挑战的深度分析。 趋势一:人工智能和机器学习在测试中的应用 AI和ML正在越来越多地应用于软件测试&am…

给httprunnermanager接口自动化测试平台演示参数化(五)

文章目录 一、背景1.1、前情回顾 二、参数化实现三、总结 一、背景 参数化,在使用httprunner框架的时候,参数话说实在的不是很实用,因为更多是场景化的用例编写,不用过多的去参数化批量执行,无非也就是登录注册查询啥的…

数据库系统概论 ---知识点大全(期末复习版)

(一)绪论 数据(Data):是数据库中存储的基本对象 数据的定义:描述事物的符号记录 数据的种类:文字、图形、图象、声音等 数据的特点:数据与其语义是不可分的 数据库(Database,简称DB):是长期…

数据结构与算法-跳表详解

我们知道如果一个数组是有序的,查询的时候可以使用二分法进行查询,时间复杂度可以降到 O(logn) ,但如果链表是有序的,我们仍然是从前往后一个个查找,这样显然很慢,这个时候我们可以使用跳表(Ski…

chatgpt赋能python:Python如何依次取字符——一种简单有效的方法

Python如何依次取字符——一种简单有效的方法 1. 介绍 Python 常常被用于编写文本处理脚本,而文本处理中的一个常见任务就是依次取字符。本文将介绍一种简单高效的方法,让您可以在 Python 中便捷地完成此操作。 2. 如何依次取字符 Python 中的字符串…

黑客入门必备指南

在探讨黑客如何入门之前,首先我们的思想要端正。 作为一名黑客,必须要有正直善良的价值观。 或许你听过这么一句话“能力越大,责任越大”作为一名黑客就是如此,黑客的技术越精湛,能力就越大,就越不能去干…

spark入门 Linux模式 Local模式 (二)

一、下载对应的spark包 https://archive.apache.org/dist/spark/spark-3.0.0/ 我这里下载的是spark-3.0.0-bin-hadoop3.2.tgz 二、解压 tar -zvxf spark-3.0.0-bin-hadoop3.2.tgz三、启动 再解压路径的bin目录执行下 ./spark-shell 四、测试 WordCount代码例子 sc.textFil…

接口测试-使用mock生产随机数据

在做接口测试的时候,有的接口需要进行大量的数据进行测试,还不能是重复的数据,这个时候就需要随机生产数据进行测试了。这里教导大家使用mock.js生成各种随机数据。 一、什么是mock.js mock.js是用于生成随*机数据,拦截 Ajax 请…

uniapp引入uView正确步骤及误区

1.导入uview组件库 2.导入成功后在main.js里引入 import uView from /uni_modules/uview-ui Vue.use(uView)3.在App.vue里引入样式文件 import "/uni_modules/uview-ui/index.scss";4.在pages.json里添加配置 "easycom": {"^u-(.*)": "/…

大聪明教你学Java | parallelStream().forEach() 的踩坑日记

前言 🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。 🍊支持作者: 点赞👍、关注💖、留言&#x1f4…

springboot学生管理系统(含源码+数据库)

本次系统开发所用到的Java语言、Spring框架、SpringMVC框架、MyBatis框架、SpringBoot框架以及MySQL。 1.系统分析 (1)教师管理需求,学校想轻松的查阅指定教师的信息,学校对教师进行一个基本的信息管理,学校可以方便…

【python】脚本编写

这里写自定义目录标题 欢迎使用python来编写脚本环境搭建 欢迎使用python来编写脚本 测试方向,测试报告,单元测试 环境搭建 python环境搭建 下载地址 https://www.python.org/ 文档 https://docs.python.org/3/ pycharm的环境 使用chatgpt来实现代码功…