网上也找到类似的文章,但是基本都不到实用级别,就是不能直接用。在参照网上的文章及与AI沟通N次后终于完善可以在实际项目上
- 创建jar文件动态加载类
java
@Component
@Slf4j
public class PluginRegistry {
@Autowired
private GenericApplicationContext applicationContext;
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
private final Map<String, URLClassLoader> loaders = new ConcurrentHashMap<>();
public void loadPlugin(String jarPath) throws Exception {
// 将 JAR 文件转换为 URL
File jarFile = new File(jarPath);
if (!jarFile.exists()) {
throw new IllegalArgumentException("JAR file not found: " + jarPath);
}
URL jarUrl = jarFile.toURI().toURL();
URLClassLoader classLoader = new URLClassLoader(
new URL[]{jarUrl},
Thread.currentThread().getContextClassLoader()
);
Thread.currentThread().setContextClassLoader(classLoader);
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
Set<BeanDefinition> candidateComponents =
scanner.findCandidateComponents("com.snail.model"); // 替换为目标包路径
// 注册扫描到的 Controller 到 Spring 容器
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();
for (org.springframework.beans.factory.config.BeanDefinition bd : candidateComponents) {
String className = bd.getBeanClassName();
Class<?> clazz = classLoader.loadClass(className);
applicationContext.registerBean(clazz);
}
requestMappingHandlerMapping.afterPropertiesSet();
log.info("加载插件成功{}",requestMappingHandlerMapping.getHandlerMethods().size());
loaders.put(jarPath, classLoader);
}
}
加载jar包,并扫描Commpent 注解,并注册到spring容器中,同时更新RequestMappingHandler(这样Controller就能生效了) 。 --- 应该还需要实现spring boot 的SPI 等,以支持更多场景。
- 发布动态加载jar文件的接口
这个简单 就是创建一个controller 来调用动态加载的方法。 - 准备测试jar
随意创建一个springmvc的项目并打包成jar文件即可。 - 测试结果
启动主程序,通过接口将测试的jar加载进来,在访问新加载进来的接口测试