轻量级 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 { @Autowired private Extension extension; /** * 测试接口 */ @GetMapping public 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); // 添加到框架 ClassLoader JarIndexClassLoader 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 { @Override public String getId() { return "default"; } @Override public boolean isCritical() { return false; } @Override public byte[] getValue() { return new byte[0]; } @Override public 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 { @Override public String getId() { return "example"; } @Override public boolean isCritical() { return false; } @Override public byte[] getValue() { return new byte[0]; } @Override public 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,原因是卸载了之前加载的启动器,条件注解生效,实现类又变化了!
从而实现了启动器的热加载,感兴趣的同学可以试一下。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
CrateDB 5.10.8 发布,分布式 SQL 数据库
CrateDB 是一个分布式的 SQL 数据库,使得实时存储和分析大量的机器数据变得简单。CrateDB 提供了通常与 NoSQL 数据库相关的可扩展性和灵活性,最小的 CrateDB 集群可以轻松地每秒摄取数万条记录。这些数据可以在整个集群中实时地、临时地、并行地进行查询。 CrateDB 5.10.8 现已正式发布,该版本更新内容如下: 修复了当需要该节点的查询即将在另一个节点上启动时,节点断开连接可能导致内存泄漏的竞争条件。 修复了版本 5.6.0中引入的回归问题,该问题导致在 publisher source table 包含一些 non-active primary shards 时(例如在重启节点时),逻辑复制会停止。建议先升级 subscriber cluster,然后再升级 publisher cluster,以便正确应用此修复。此修复仅在 publisher 和 subscriber clusters 均运行5.10.8或更高版本时有效。 修复了一个问题,即在 sys.repositories 表中,Azure 存储库的sas_token和key设置以未屏蔽设置的形式...
- 下一篇
阿里通义实验室开源检索增强预训练框架 MaskSearch
阿里通义实验室发布并开源了 MaskSearch 预训练框架,声称能让 AI 学会“主动搜索 + 多步推理”,从而更准确、更智能地回答复杂问题。 根据介绍,MaskSearch 的核心在于它提出的一种全新预训练任务——检索增强掩码预测(RAMP),在这个任务中,模型需要填补句子中的掩码部分,并且必须通过主动搜索和多步推理来完成任务。 例如,给定一个句子: Andrew Barto received his[mask]with distinction in[mask]fromthe University of Michigan in1970. AI 需要通过搜索引擎查找相关信息,逐步推理出被遮盖的部分。模型首先分析上下文,判断需要查找的信息是“学位类型”和“专业方向”。随后,它调用搜索引擎进行查询,得到关于 Andrew Barto 的相关信息,并从中提取出关键片段:“Andrew Barto, B.S., math, University of Michigan, 1970”。 接着,AI 进行推理整合,最终填补掩码输出完整句子: AndrewBartoreceived his...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS关闭SELinux安全模块
- Docker安装Oracle12C,快速搭建Oracle学习环境