{"id":19237520,"url":"https://github.com/core-lib/slot-maven-plugin","last_synced_at":"2026-03-05T21:32:26.623Z","repository":{"id":48299403,"uuid":"170988148","full_name":"core-lib/slot-maven-plugin","owner":"core-lib","description":"Spring Boot 可插件化拓展改造器，让 Spring-Boot 应用支持加载外部 jar 包，实现插件化拓展。","archived":false,"fork":false,"pushed_at":"2021-08-02T17:16:45.000Z","size":20,"stargazers_count":45,"open_issues_count":1,"forks_count":21,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-21T06:41:50.031Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/core-lib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-16T09:54:53.000Z","updated_at":"2025-03-19T01:47:30.000Z","dependencies_parsed_at":"2022-08-26T16:11:49.528Z","dependency_job_id":null,"html_url":"https://github.com/core-lib/slot-maven-plugin","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/core-lib/slot-maven-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/core-lib%2Fslot-maven-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/core-lib%2Fslot-maven-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/core-lib%2Fslot-maven-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/core-lib%2Fslot-maven-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/core-lib","download_url":"https://codeload.github.com/core-lib/slot-maven-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/core-lib%2Fslot-maven-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30150435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T21:15:50.531Z","status":"ssl_error","status_checked_at":"2026-03-05T21:15:11.173Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T16:27:07.175Z","updated_at":"2026-03-05T21:32:24.535Z","avatar_url":"https://github.com/core-lib.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Slot [![](https://jitpack.io/v/core-lib/slot-maven-plugin.svg)](https://jitpack.io/#core-lib/slot-maven-plugin)\r\n\r\nSpring Boot 可插件化拓展改造器，让 Spring-Boot 应用支持加载外部 jar 包，实现插件化拓展。\r\n\r\nGitHub: https://github.com/core-lib/slot-maven-plugin\r\n\r\n#### Slot: 在计算机行业指的就是周边元件扩展插槽。\r\n\r\n## 问题描述\r\nSpring-Boot 项目打包后是一个FatJar 即把所有依赖的第三方jar也打包进自身的jar中，运行时 classpath 包括 FatJar 中的 BOOT-INF/classes 目录和 BOOT-INF/lib 目录下的所有jar。\r\n\r\n那么问题是要想加载外部化 jar 就只能打包期间把 jar 依赖进去，无法实现可插拔式插件化拓展。\r\n\r\n[Slot](https://github.com/core-lib/slot-maven-plugin) 就是一个可以将 Spring-Boot 项目升级为可支持加载外部 jar 的 Maven 插件。\r\n\r\n## 原理说明\r\n\r\n一个 Spring-Boot JAR 启动的流程可以分为以下几步：\r\n1. 通过 java -jar spring-boot-app.jar args... 命令启动\r\n2. JVM 读取该 jar 的 META-INF/MANIFEST.MF 文件中的 Main-Class，在 Spring-Boot JAR 中这个值通常为 org.springframework.boot.loader.JarLauncher \r\n3. JVM 调用该类的 main 方法，传入参数即上述命令中参数\r\n4. JarLauncher 构建 ClassLoader 并反射调用 META-INF/MANIFEST.MF 中的 Start-Class 类的 main 方法，通常为项目中的 Application 类 \r\n5. Application 类的 main 方法调用 SpringApplication.run(Application.class, args); 以最终启动应用\r\n\r\n[Slot](https://github.com/core-lib/slot-maven-plugin) 的核心原理是：\r\n1. 拓展 org.springframework.boot.loader.JarLauncher 实现根据启动命令参数读取外部 jar 包并且加入至 classpath 中\r\n2. 修改 META-INF/MANIFEST.MF 中的 Main-Class 为拓展的 JarLauncher\r\n\r\n## 环境依赖\r\n1. JDK 1.7 +\r\n2. Spring-Boot\r\n\r\n##  使用说明\r\n```xml\r\n\u003cproject\u003e\r\n    \u003c!-- 设置 jitpack.io 插件仓库 --\u003e\r\n    \u003cpluginRepositories\u003e\r\n        \u003cpluginRepository\u003e\r\n            \u003cid\u003ejitpack.io\u003c/id\u003e\r\n            \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\r\n        \u003c/pluginRepository\u003e\r\n    \u003c/pluginRepositories\u003e\r\n    \u003c!-- 添加 Slot Maven 插件 --\u003e\r\n    \u003cbuild\u003e\r\n        \u003cplugins\u003e\r\n            \u003cplugin\u003e\r\n                \u003cgroupId\u003ecom.github.core-lib\u003c/groupId\u003e\r\n                \u003cartifactId\u003eslot-maven-plugin\u003c/artifactId\u003e\r\n                \u003cversion\u003e1.0.2\u003c/version\u003e\r\n                \u003cexecutions\u003e\r\n                    \u003cexecution\u003e\r\n                        \u003cgoals\u003e\r\n                            \u003cgoal\u003etransform\u003c/goal\u003e\r\n                        \u003c/goals\u003e\r\n                        \u003cphase\u003epackage\u003c/phase\u003e\r\n                        \u003cconfiguration\u003e\r\n                            \u003c!-- optional\r\n                            \u003csourceDir/\u003e\r\n                            \u003csourceJar/\u003e\r\n                            \u003ctargetDir/\u003e\r\n                            \u003ctargetJar/\u003e\r\n                            --\u003e\r\n                        \u003c/configuration\u003e\r\n                    \u003c/execution\u003e\r\n                \u003c/executions\u003e\r\n            \u003c/plugin\u003e\r\n        \u003c/plugins\u003e\r\n    \u003c/build\u003e\r\n\u003c/project\u003e\r\n```\r\n\r\n## 参数说明\r\n| 参数名称 | 命令参数名称 | 参数说明 | 参数类型 | 缺省值 | 示例值 |\r\n| :------ | :----------- | :------ | :------ | :----- | :----- |\r\n| sourceDir | -Dslot.sourceDir | 源jar所在目录 | File | ${project.build.directory} | 文件目录 |\r\n| sourceJar | -Dslot.sourceJar | 源jar名称 | String | ${project.build.finalName}.jar | 文件名称 |\r\n| targetDir | -Dslot.targetDir | 目标jar存放目录 | File | ${project.build.directory} | 文件目录 |\r\n| targetJar | -Dslot.targetJar | 目标jar名称 | String | ${project.build.finalName}.slot | 文件名称 |\r\n\r\n插件的默认执行阶段是 package ， 当然也可以通过使用以下命令来单独执行。\r\n```text\r\nmvn slot:transform\r\n\r\nmvn slot:transform -Dslot.targetJar=your-spring-boot-app-slot.jar\r\n```\r\n\r\n默认情况下，通过 slot 升级后的 jar 名称为 ${project.build.finalName}-slot.jar ，可以通过插件配置或命令参数修改。\r\n\r\n## 注意事项\r\n```xml\r\n\u003cplugin\u003e\r\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\r\n    \u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\r\n    \u003c!-- 需要将executable和embeddedLaunchScript参数删除，目前还不能支持对该模式Jar的升级！\r\n    \u003cconfiguration\u003e\r\n        \u003cexecutable\u003etrue\u003c/executable\u003e\r\n        \u003cembeddedLaunchScript\u003e...\u003c/embeddedLaunchScript\u003e\r\n    \u003c/configuration\u003e\r\n    --\u003e\r\n\u003c/plugin\u003e\r\n```\r\n\r\n## 启动应用\r\n\r\nSlot 支持使用两个参数来指定要加载的外部 jar 包：\r\n1. --slot.root 即外部 jar 的根路径，缺省情况下为 Spring-Boot JAR 包的目录。\r\n2. --slot.path 即外部 jar 的路径，支持设置多个，支持 ANT 表达式风格。\r\n\r\n```text\r\njava -jar spring-boot-app-slot.jar --slot.root=/absolute/root/ --slot.path=foo.jar  --slot.path=bar.jar\r\n\r\njava -jar spring-boot-app-slot.jar --slot.path=/relative/path/to/plugin.jar\r\n\r\njava -jar spring-boot-app-slot.jar --slot.path=/relative/path/to/**.jar\r\n``` \r\n\r\nANT 表达式通配符说明\r\n\r\n| 通配符 | 含义 | 示例 |\r\n| :----- | :--- | :--- |\r\n| ** | 任意个字符及目录 | /plugins/**.jar 即 /plugins 目录及子目录的所有 .jar 后缀的文件 |\r\n| * | 任意个字符 | /plugins/*.jar 即 /plugins 目录的所有 .jar 后缀的文件 |\r\n| ? | 单个字符 | ???.jar 即当前目录所有名称为三个任意字符及以 .jar 为后缀的文件 |\r\n\r\n通配符可以随意组合使用！ 例如 /plugins/\\*\\*/plugin-\\*-v???.jar\r\n\r\n## 使用技巧\r\n由于通过 Slot 加载后的外部 jar 实际上和 Spring-Boot JAR 中的 jar 处于同一个 ClassLoader 所以外部插件和母体应用之间是一个平级的关系，\r\n外部插件可以引用母体应用中的 class 同样母体应用也可以引用外部插件的 class。\r\n\r\n由于外部插件项目或模块通常也会依赖另外的第三方jar，所以外部插件与母体应用集成运行时也需要把另外的第三方jar通过--slot.path参数加载进来。\r\n推荐使用 maven-dependency-plugin 在打包时将需要用到的第三方jar拷贝到指定目录，最后通过ANT表达式方式一起加载运行。\r\n```xml\r\n\u003cplugin\u003e\r\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\r\n    \u003cartifactId\u003emaven-dependency-plugin\u003c/artifactId\u003e\r\n    \u003cexecutions\u003e\r\n        \u003cexecution\u003e\r\n            \u003cphase\u003epackage\u003c/phase\u003e\r\n            \u003cgoals\u003e\r\n                \u003cgoal\u003ecopy-dependencies\u003c/goal\u003e\r\n            \u003c/goals\u003e\r\n            \u003cconfiguration\u003e\r\n                \u003cincludeScope\u003eruntime\u003c/includeScope\u003e\r\n                \u003coutputDirectory\u003e${project.build.directory}/dependencies\u003c/outputDirectory\u003e\r\n            \u003c/configuration\u003e\r\n        \u003c/execution\u003e\r\n    \u003c/executions\u003e\r\n\u003c/plugin\u003e\r\n```\r\n\r\n或者使用 maven-shade-plugin 插件把相关的第三方jar资源通通打包进一个。\r\n```xml\r\n\u003cplugin\u003e\r\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\r\n    \u003cartifactId\u003emaven-shade-plugin\u003c/artifactId\u003e\r\n    \u003cversion\u003e3.1.1\u003c/version\u003e\r\n    \u003cexecutions\u003e\r\n        \u003cexecution\u003e\r\n            \u003cphase\u003epackage\u003c/phase\u003e\r\n            \u003cgoals\u003e\r\n                \u003cgoal\u003eshade\u003c/goal\u003e\r\n            \u003c/goals\u003e\r\n            \u003cconfiguration\u003e\r\n                ...\r\n            \u003c/configuration\u003e\r\n        \u003c/execution\u003e\r\n    \u003c/executions\u003e\r\n\u003c/plugin\u003e\r\n```\r\n另外需要注意的是，当母体应用和外部插件有相同的第三方依赖时，推荐让外部插件模块以 \u0026lt;scope\u0026gt;provided\u0026lt;/scope\u0026gt; 的方式依赖之。\r\n\r\n\r\n下面是作者想到的一些插件化拓展的方案：\r\n\r\n1. IoC方式：母体应用声明接口，外部插件实现接口并且通过 @Component @Service 或其他注解让Spring 容器管理， 母体应用通过 @Resource @Autowired 来注入。\r\n\r\n2. SPI方式：母体应用声明接口，外部插件实现接口并且配置于 META-INF/services/ 下，母体应用通过 ServiceLoader 加载接口的实现类。\r\n\r\n3. AOP方式：外部插件通过 Spring Aspect 技术实现对母体应用的切面拦截。\r\n\r\n\r\n## 版本记录\r\n* 1.0.2 升级[LoadKit](https://github.com/core-lib/loadkit)依赖版本解决ANT表达式无法正确匹配**/*通配符的问题\r\n\r\n* 1.0.1 bug 修复\r\n\r\n* 1.0.0 第一个正式版发布\r\n\r\n## 协议声明\r\n[Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0)\r\n\r\n## 联系作者\r\nQQ 646742615 不会钓鱼的兔子","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcore-lib%2Fslot-maven-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcore-lib%2Fslot-maven-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcore-lib%2Fslot-maven-plugin/lists"}