轻量级 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条评论来说两句吧...

微信收款码
支付宝收款码