轻量级 ioc 框架 loveqq,支持接口上传 jar 格式的 starter 启动器并支持热加载其中的 bean

轻量级 ioc 框架 loveqq,支持接口上传 jar 格式的 starter 启动器并支持热加载其中的 bean


热加载 starter 启动器代码示例:

package com.kfyty.demo;import com.kfyty.loveqq.framework.boot.K;
import com.kfyty.loveqq.framework.boot.context.ContextRefresher;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Autowired;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.BootApplication;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component;
import com.kfyty.loveqq.framework.core.autoconfig.condition.annotation.ConditionalOnMissingBean;
import com.kfyty.loveqq.framework.core.lang.JarIndexClassLoader;
import com.kfyty.loveqq.framework.core.utils.IOC;
import com.kfyty.loveqq.framework.web.core.annotation.GetMapping;
import com.kfyty.loveqq.framework.web.core.annotation.RequestMapping;
import com.kfyty.loveqq.framework.web.core.annotation.RestController;
import com.kfyty.loveqq.framework.web.core.autoconfig.annotation.EnableWebMvc;
import com.kfyty.loveqq.framework.web.core.multipart.MultipartFile;
import lombok.extern.slf4j.Slf4j;import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.security.cert.Extension;
import java.util.Collections;
import java.util.UUID;
import java.util.jar.JarFile;@Slf4j
@EnableWebMvc
@RestController
@BootApplication
@RequestMapping(expose = true)                  // 自动暴露 public 方法为 POST http 接口
public class Main {@Autowiredprivate Extension extension;/*** 测试接口*/@GetMappingpublic String sayHello() {return extension.getId();}/*** 加载插件** @param jar jar 包 启动器* @return 上传后的 jar 包绝对路径,卸载启动器时需要提供该返回值*/public String loadPlugin(MultipartFile jar) throws Exception {// 保存到本地String filePath = "D:\\temp\\jar\\" + UUID.randomUUID().toString().replace("-", "") + "\\" + jar.getOriginalFilename();File jarFile = new File(filePath);jar.transferTo(jarFile);// 添加到框架 ClassLoaderJarIndexClassLoader classLoader = (JarIndexClassLoader) IOC.class.getClassLoader();classLoader.addJarIndex(Collections.singletonList(new JarFile(jarFile)));// 刷新上下文ContextRefresher.refresh(IOC.getApplicationContext());return jarFile.getAbsolutePath();}/*** 卸载启动器** @param jarPath {@link #loadPlugin(MultipartFile)} 的返回值*/public String unloadPlugin(String jarPath) throws Exception {// 构建 File 对象File jarFile = new File(jarPath);// 从框架 ClassLoader 移除JarIndexClassLoader classLoader = (JarIndexClassLoader) IOC.class.getClassLoader();classLoader.removeJarIndex(Collections.singletonList(new JarFile(jarFile)));// 刷新上下文ContextRefresher.refresh(IOC.getApplicationContext());return "ok";}public static void main(String[] args) throws Exception {K.run(Main.class, args);}/*** 默认实现*/@Component@ConditionalOnMissingBean(Extension.class)public static class DefaultExtension implements Extension {@Overridepublic String getId() {return "default";}@Overridepublic boolean isCritical() {return false;}@Overridepublic byte[] getValue() {return new byte[0];}@Overridepublic void encode(OutputStream out) throws IOException {}}
}

然后,新建一个项目,添加如下类:

package com.kfyty.graal.example;import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component;import java.io.IOException;
import java.io.OutputStream;
import java.security.cert.Extension;/*** 动态加载示例实现*/
@Component
public class ExampleExtension implements Extension {@Overridepublic String getId() {return "example";}@Overridepublic boolean isCritical() {return false;}@Overridepublic byte[] getValue() {return new byte[0];}@Overridepublic void encode(OutputStream out) throws IOException {}
}

并在 k.factories 中添加:

com.kfyty.loveqq.framework.core.autoconfig.annotation.EnableAutoConfiguration=com.kfyty.graal.example.ExampleExtension

然后打成 jar 包,就是一个启动器了。

接着启动第一段代码的 main 方法后:

先访问:http://localhost:8080/sayHello,将返回 default

然后使用 postman 上传启动器 jar 包:http://127.0.0.1:8080/loadPlugin,此时将动态加载上传的启动器,并刷新 ioc 容器

然后再访问:http://localhost:8080/sayHello,将返回 example,原因是加载了新的启动器,条件注解生效,实现类变化了!

然后再访问:http://127.0.0.1:8080/unloadPlugin,将第二步的返回值作为入参传入,此时将卸载启动器,并刷新 ioc 容器

然后再访问:http://localhost:8080/sayHello,将返回 default,原因是卸载了之前加载的启动器,条件注解生效,实现类又变化了!

从而实现了启动器的热加载,感兴趣的同学可以试一下。

gitee/github/gitcode: loveqq-framework

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

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

相关文章

图论----4.实现 Trie (前缀树)

题目链接 /** Trie前缀树基本结构: (多叉单词查找树)每个Trie中包含一个Trie数组与一个结束标识 Trie[] children Trie数组,每个节点都可存放一个Trie,其索引代表该节点对应的字符。 boolean isEnd 结束标识, 代表当前节点是否是一个完整单词的结尾巴 前缀树insert流程: 计算第…

DELL R730XD服务器调整风扇转速

注意: 进入iDRAC的Web管理界面,左侧iDRAC设置->网络->IPMI设置,勾选启用LAN上的IPMI。使用ipmitool调整,服务器电源断开后就会失效,如果想要永久生效,就在服务器端写一个开机自启动脚本。先关闭风扇…

从C++编程入手设计模式——策略设计模式

从C编程入手设计模式——策略设计模式 ​ 在我们平时写程序的过程中,经常会遇到这样的情况:一个对象的某个功能可以有多种实现方式,而且可能会根据不同的场景切换这些方式。比如一只动物可以发出不同的叫声,一个排序器可以使用不…

网页中调用自定义字体可以通过 ‌CSS‌ 的 @font-face 规则实现

以下是详细方法: ‌1. 使用系统默认字体‌ 如果只是希望指定字体,可以直接使用 font-family: body { font-family: "Microsoft YaHei", "PingFang SC", sans-serif; /* 中英文适配 */ } ‌2. 使用自定义字体&…

[CVPR 2025] DeformCL:基于可变形中心线的3D血管提取新范式

CVPR 2025 | DeformCL:基于可变形中心线的3D血管提取新范式 论文信息 标题:DeformCL: Learning Deformable Centerline Representation for Vessel Extraction in 3D Medical Image作者:Ziwei Zhao, Zhixing Zhang, Yuhang Liu, 等单位&…

BeckHoff <---> Keyence (LJ-X8000) 2D相机 Profinet 通讯

目录 ​编辑 一、 设备介绍 1、产品特点 2、控制器选择 3、应用领域 二、PLC通讯接口配置 1、PLC添加GSDML文件 2、定义输入3、变量实例化 3、定义输出变量实例化 三、设备通讯接口数据类型定义 1、定义全局结构体数据 2、定义 INput Decode结构体数据 四、通讯…

electron在单例中实现双击打开文件,并重复打开其他文件

单实例的思路 首次通过双击文件打开应用 将filePath传给render 使用中的应用,再次双击打开文件 第一个实例创建时,同时创建一个通信服务器net.createServer()第二个实例创建时,连接第一个服务器net.createConnection()将再次打开的filePath传…

一、基础架构层:高性能引擎基石

1. ECS架构工业级实现 // EnTT实战示例:导弹系统组件定义 struct Position { vec3 value; }; struct Velocity { vec3 value; }; struct ExplodeWhen { float distance; };entt::registry registry;// 实体创建与组件绑定 auto missile registry.create(); regist…

rockylinuxapache和Linux服务配置

目录 apache nginx 反向代理配置[rootk8s2 ~]# [rootk8s2 ~]# cat /etc/nginx/conf.d/webserver.confserver { listen 80; server_name www.sxy1.com; location / { root /var/www/html; index index.html; } location /py/{ …

ai 幻觉

ai幻觉: 感知人类观察者不存在或无法感知的模式或对象,从而产生无意义或完全不准确的输出 有时 AI 算法会生成并非基于训练数据的输出结果,继而被转换器错误解码或不遵循任何可识别的模式。换句话说,它会在给出响应时“产生幻觉” 致因:训练…

freeRTOS移植实验

提示:文章 文章目录 前言一、背景第6章节 二、2.12.2 三、3.1 总结 前言 前期疑问: 本文目标: 一、背景 在家里先使用野火网盘资料里的freeRTOS源码,网盘里是v9.0.0。 J:\野火\STM32F103ZET6_霸道开发板\A盘(资料盘…

食品加工温控场景:PROFIBUS转MODBUS的温控表连接规范

在现代的工业自动化领域里,实现不同通信协议设备间无缝对接的技术日益受到重视。这不仅关乎系统整合性和效率的提升,更是实现复杂工业过程自动化的必经之路。特别是在众多的通信协议中,MODBUS和PROFIBUS这两种广泛使用的协议因其各自的优势而…

【动态规划】回文串(二)

📝前言说明: 本专栏主要记录本人的动态规划算法学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码;&…

Ubuntu22.04.5 桌面版然后安装 VMware 17

安装 VMware 需要 GCC 12版本 标题通过 PPA 安装 这是最简单的方法,适用于大多数 Ubuntu 版本。 步骤 1:添加 PPA 仓库 sudo apt update sudo apt install software-properties-common sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt…

深入解析 MySQL 架构:从基础到高级

MySQL 是一款广泛使用的开源关系型数据库管理系统,以其高性能、可靠性和灵活性而闻名。无论是小型创业公司还是大型企业,MySQL 都是许多应用程序的首选数据库解决方案。本文将深入探讨 MySQL 的架构设计,帮助读者更好地理解其内部工作机制&am…

BACnet协议移植适配实现BACnet/IP和BACnet MSTP相关功能

1、从GitHub或者其他网站下载最新的协议栈源码 源码结构如图所示: 其中src是协议栈源码,可直接拿来使用,apps里面是一些功能的应用示例,有BACnet IP,BACnet MSTP,BACnet Router等功能。 2、协议栈移植完成…

Ubuntu 22.04.1 LTS 离线安装Docker(最快方法,仅需一个压缩文件和两个脚本)

作者亲测:亲测有效无bug。 利用ubuntu22.04下载完docker-27.4.1.tgz,然后按照下面方法安装。选择sudo方法。 tips:这个ubuntu22.04是迁移后的服务器的版本,不是迁移前的版本。 下载 下载地址 : https://download.docker.com/linux/static/stable/x86_…

Tkinter --按钮点击事件应用场景

第二章 事件处理 目录 第二章 事件处理 四、事件处理 4.1 按钮点击事件 4.1.1信息展示类场景 1. 静态文本说明 ​编辑 2. 动态状态显示 4.1.2.界面美化与装饰 1. 图像 / 图标展示 ​编辑 2. 分隔与布局辅助 4.1.3 交互反馈与提示 1. 操作结果提示 2. 帮助与说明文本…

计算机网络学习笔记:TCP流控、拥塞控制

文章目录 前言一、TCP流量控制1.1、案例:三次流量控制1.2、持续计时器 二、TCP拥塞控制2.1、拥塞控制的指标2.2、慢开始算法和拥塞避免算法2.3、快重传算法和快恢复算法2.4、练习 三、TCP拥塞控制与网际层拥塞控制总结 前言 TCP协议中的流量和拥塞,是两个…

【Linux】Tomcat搭建

前言 Tomcat Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。 JSP JSP是一种跨平台的动态网页技术标准,可以…