当前位置: 代码网 > it编程>编程语言>Java > SpringBoot加载外部Jar实现功能按需扩展

SpringBoot加载外部Jar实现功能按需扩展

2025年06月17日 Java 我要评论
实现方案实现这个很简单,只需要完成下面两步:想办法将 class 加载到 jvm使 spring 扫描到 class有时候java中的各种框架以及复杂的概念源码给我们造成了很大理解障碍,特别是spri

实现方案

实现这个很简单,只需要完成下面两步:

  • 想办法将 class 加载到 jvm
  • 使 spring 扫描到 class

有时候java中的各种框架以及复杂的概念源码给我们造成了很大理解障碍,特别是spring家族的所以先想清楚大致实现步骤比较好

将class加载到jvm

现在我们设定需要加载的 jar 在 /user/local/java/plugins 目录下,对于第 1 步,现在有如下几种实现方式:

  • 扩大 -cp 由 appclassloader 帮我们加载外部 jar
  • 使用 springboot 提供的启动参数 loader.path 实现
  • 自定义 classloader 实现加载指定位置的 jar

其中 1 和 3 是jdk提供的方案,2是 springboot 扩展的方案,毕竟 springboot 也需要自定义加载很多类顺带扩展了一个参数出来

方案1

扩大 -cp 由 appclassloader 帮我们加载外部 jar

可以使用 classpath 指定类加载的路径,但 classpath 的生效是有条件的,这里其实对应了 jar 包的两种启动方式:通过jar包里的main函数启动或者运行jar启动

springboot 打包后 manifest.mf 内容如下:

manifest-version: 1.0
created-by: maven jar plugin 3.2.2
build-jdk-spec: 18
implementation-title: intelligent-soul
implementation-version: 0.0.1-snapshot
main-class: org.springframework.boot.loader.jarlauncher
start-class: com.test.myapplication
spring-boot-version: 2.6.15
spring-boot-classes: boot-inf/classes/
spring-boot-lib: boot-inf/lib/
spring-boot-classpath-index: boot-inf/classpath.idx
spring-boot-layers-index: boot-inf/layers.idx

所以需要使用 main 函数启动的方式,不能使用之前的常用的 jar 包启动方式了。对于 springboot 应用 main-class 是 jarlauncher 所以此时启动命令要改成

java  -cp  /user/local/java/plugins org.springframework.boot.loader.jarlauncher
  • 优点:实现简单
  • 缺点:每个 jar 包启动命令都一样了,不好区分

方案2

使用springboot扩展的启动参数,使用java -jar 配合loader.path参数

因为 spring boot 程序大多是打成 jar 包,使用 java -jar boot.jar 的方式启动 (此时 -cp 无效),可以使用 loader.path 指定类加载路径加载其他 jar,但 loader.path 生效也是有条件的:

springboot 默认打包方式的main-classjarlauncher

配置 main-class

为了使 loader.path 参数生效需要生成 jar 包的 main-class 项配置为 propertieslauncher,在 maven 中如下配置,可参考 using the propertieslauncher:

<build>
     <plugins>
         <plugin>
             <groupid>org.springframework.boot</groupid>
             <artifactid>spring-boot-maven-plugin</artifactid>
             <configuration>
                 <!-- 打包时排除scope为system的包 -->
                 <includesystemscope>false</includesystemscope>
                 <!-- jvm启动时通过-dloader.path加载包,必须指定layout为zip,否则-dloader.path无效!!! -->
                 <layout>zip</layout>
             </configuration>
             <executions>
                 <execution>
                     <goals>
                         <goal>repackage</goal>
                     </goals>
                 </execution>
             </executions>
         </plugin>
     </plugins>
     <finalname>test</finalname>
</build>

其中 layout 可配置值如下:

1、jar,即通常的可执行 jar

main-class: org.springframework.boot.loader.jarlauncher

2、war,即通常的可执行war,需要的 servlet 容器依赖位于 web-inf/lib-provided

main-class: org.springframework.boot.loader.warlauncher

3、zip,即dir,类似于 jar

main-class: org.springframework.boot.loader.propertieslauncher

4、module,将所有的依赖库打包(scopeprovided的除外),但是不打包 spring boot 的任何launcher

5、none,将所有的依赖库打包,但是不打包 spring boot 的任何 launcher

无论启动类是 jarlauncher 或者 propertieslauncherloader.path 引入的 jar 和 spring boot jar 包中 boot-info/lib 包下 jar 都是使用类加载器 org.springframework.boot.loader.launchedurlclassloader 进行加载,也就是说他们使用的是同一个类加载器。这个类加载器主要就是负责加载 jar 包里的 jar 的加载,因为jdk没有实现该功能所以 springboot 定义了该类

注意到同一个程序,打包成不同类型时,propertieslauncher (20s) 比 jarlauncher (8s) 启动慢很多。

方案3

自定义类加载器,加载固定目录下的jar包或者读取环境变量路径

这种方式需要程序启动的某个节点,调用自定义类加载器去加载指定目录下的 jar 包,时间点不是很好控制。但这个定制化程度比较高。

//可以在这里调用自定义类加载
springapplication.run(springbootdemo.class, args);

方案4

通过设置-xbootclasspath/a或者 extention classloader通过改变参数java.ext.dirs实现

会改变系统类加载器加载行为不安全不推荐!!!

加载后的类如何扫描进入spring容器

对于业务 jar 包类,可以预先在springboot中指定好扫描包路径,那么只需要插件包路径是com.demo开头即可,如下

@springbootapplication(scanbasepackages = {"com.demo"})
public class springbootdemoapplication {
    public static void main(string[] args) {
        springapplication.run(springbootdemoapplication.class, args);
    }

如不符合包名前缀一致的情况,需要在jar包meta-inf下的spring.factories指定好自动装配的类即可如 mybatis-plus:

# auto configure
org.springframework.boot.env.environmentpostprocessor=\
  com.baomidou.mybatisplus.autoconfigure.safetyencryptprocessor
org.springframework.boot.autoconfigure.enableautoconfiguration=\
  com.baomidou.mybatisplus.autoconfigure.identifiergeneratorautoconfiguration,\
  com.baomidou.mybatisplus.autoconfigure.mybatispluslanguagedriverautoconfiguration,\
  com.baomidou.mybatisplus.autoconfigure.mybatisplusautoconfiguration

到此这篇关于springboot加载外部jar实现功能按需扩展的文章就介绍到这了,更多相关springboot加载外部jar内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com