SpringBoot应用中同名包类加载冲突的解决方案咨询
解决Spring Boot同名包类加载冲突的可行方案
方案1:Maven Shade插件重打包其中一个依赖包
既然无法修改原依赖包,可通过Maven Shade插件将其中一个jar(比如jar1)的inspector包重命名为唯一名称(如inspector.v1),再依赖重打包后的jar:
- 在diffToolv1的pom.xml中配置Shade插件:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern>inspector</pattern> <shadedPattern>inspector.v1</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>
- 执行
mvn package生成重打包后的jar,替换diffToolv1中原有的jar1依赖为这个重打包后的jar - 修改diffToolv1中所有引用
inspector包的代码,改为引用inspector.v1
方案2:自定义类加载器隔离不同依赖
为diffToolv1和diffToolv2分别创建独立的类加载器,加载各自对应的jar,避免类路径冲突:
- 编写自定义类加载器,继承
URLClassLoader,仅加载指定的jar文件:
public class CustomJarClassLoader extends URLClassLoader { public CustomJarClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent); } @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // 仅加载指定包下的类,其他类委托给父类加载器 if (name.startsWith("inspector")) { synchronized (getClassLoadingLock(name)) { Class<?> c = findLoadedClass(name); if (c == null) { c = findClass(name); } if (resolve) { resolveClass(c); } return c; } } return super.loadClass(name, resolve); } }
- 在diffToolv1中,使用自定义类加载器加载jar1中的
inspector类:
// 加载jar1的URL URL jar1Url = new File("path/to/jar1.jar").toURI().toURL(); CustomJarClassLoader jar1ClassLoader = new CustomJarClassLoader(new URL[]{jar1Url}, Thread.currentThread().getContextClassLoader()); // 加载需要的类 Class<?> inspectorClass = jar1ClassLoader.loadClass("inspector.YourTargetClass"); // 通过反射创建实例并调用方法 Object instance = inspectorClass.getDeclaredConstructor().newInstance(); Method method = inspectorClass.getMethod("yourMethod"); method.invoke(instance);
- 同理为diffToolv2创建对应的类加载器加载jar2,确保两个模块使用各自类加载器加载同名包类
方案3:使用Spring Boot PropertiesLauncher指定类加载优先级
Spring Boot的PropertiesLauncher支持更灵活的类路径配置,可以为不同模块指定不同的jar加载顺序:
- 修改项目启动类的依赖,使用
PropertiesLauncher:
在Parent的pom.xml中配置:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.yourpackage.ReportAnalytics</mainClass> <layout>ZIP</layout> <!-- 使用PropertiesLauncher需要指定ZIP布局 --> </configuration> </plugin> </plugins> </build>
- 创建
BOOT-INF/classpath.properties文件,指定diffToolv1优先加载jar1:
# 按顺序加载,jar1放在jar2前面 com.yourpackage.diffToolv1=lib/jar1.jar com.yourpackage.diffToolv2=lib/jar2.jar
- 打包后启动应用,确保diffToolv1加载jar1中的
inspector类
方案4:利用Java模块系统(JPMS)实现类隔离
将jar1和jar2转换为Java模块,通过模块声明实现包隔离:
- 为jar1添加
module-info.java:
module inspector.v1 { exports inspector; }
- 为jar2添加
module-info.java:
module inspector.v2 { exports inspector; }
- 在diffToolv1的
module-info.java中声明依赖inspector.v1:
module com.yourpackage.diffToolv1 { requires inspector.v1; }
- 在diffToolv2的
module-info.java中声明依赖inspector.v2:
module com.yourpackage.diffToolv2 { requires inspector.v2; }
- 修改Parent项目的构建配置,支持模块系统,确保不同模块依赖对应的模块
内容的提问来源于stack exchange,提问作者Pramod
相关产品推荐
相关产品推荐

