You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java项目中同时使用两个版本的bcprov-jdk15on Jar包?

解决方案

方案一:Maven Shade插件重命名bcprov-jdk15on-1.69.jar的包名

这是低侵入且易维护的方案,通过修改新版本bcprov的包名,让它与旧版本完全隔离,从根源避免类路径冲突。

操作步骤:

  1. 在项目Maven pom.xml中配置Shade插件,将bcprov-jdk15on-1.69的包名重命名(例如从org.bouncycastle改为org.bouncycastle.v169):
<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>org.bouncycastle</pattern>
                                <shadedPattern>org.bouncycastle.v169</shadedPattern>
                            </relocation>
                        </relocations>
                        <artifactSet>
                            <includes>
                                <include>org.bouncycastle:bcprov-jdk15on</include>
                            </includes>
                        </artifactSet>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  1. 给新引入的fintech-java-sdk-core和fintech-java-sdk-kdft依赖排除默认的bcprov依赖:
<dependencies>
    <!-- 旧版本bcprov,供原有功能使用 -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.54</version>
    </dependency>

    <!-- 新SDK依赖,排除自带的bcprov -->
    <dependency>
        <groupId>xxx</groupId>
        <artifactId>fintech-java-sdk-core</artifactId>
        <version>3.1.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15on</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>xxx</groupId>
        <artifactId>fintech-java-sdk-kdft</artifactId>
        <version>3.1.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15on</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- 重命名后的新版本bcprov,供新SDK使用 -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.69</version>
    </dependency>
</dependencies>
  1. 执行mvn package后,重命名后的bcprov包会被整合到项目Jar中。新SDK会加载重命名后的类,原有功能仍加载旧版本的org.bouncycastle包,完全隔离无冲突。

方案二:自定义类加载器隔离新SDK与新版本bcprov

如果不想修改包名,可以通过自定义类加载器,让新SDK和1.69版本的bcprov在独立类加载空间运行,与系统类加载器加载的旧版本隔离。

优化实现方式:

无需逐个加载类,直接将新SDK的Jar和1.69的bcprov Jar作为自定义类加载器的类路径,通过该加载器加载新SDK入口类,后续新SDK内部类都会由这个加载器加载,自然使用1.69版本的bcprov。

示例代码:

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class SdkClassLoader extends URLClassLoader {
    public SdkClassLoader(String[] jarPaths) throws Exception {
        super(getUrls(jarPaths), Thread.currentThread().getContextClassLoader().getParent());
    }

    private static URL[] getUrls(String[] jarPaths) throws Exception {
        URL[] urls = new URL[jarPaths.length];
        for (int i = 0; i < jarPaths.length; i++) {
            urls[i] = new File(jarPaths[i]).toURI().toURL();
        }
        return urls;
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 优先从自定义Jar路径加载
                    c = findClass(name);
                } catch (ClassNotFoundException e) {
                    // 找不到则委托父类加载器处理JDK核心类等
                    c = super.loadClass(name, resolve);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
}

使用示例:

public class SdkWrapper {
    public static void main(String[] args) throws Exception {
        String[] jarPaths = {
            "/path/to/bcprov-jdk15on-1.69.jar",
            "/path/to/fintech-java-sdk-core-3.1.0.jar",
            "/path/to/fintech-java-sdk-kdft-3.1.0.jar"
        };

        SdkClassLoader classLoader = new SdkClassLoader(jarPaths);
        Class<?> kdConfigClass = classLoader.loadClass("com.xxx.KdSdkConfig");
        Object defaultClient = kdConfigClass.getMethod("getDefaultClient").invoke(null);
        
        // 后续操作通过反射完成,可封装Wrapper类简化调用
    }
}

这种方式下,新SDK的所有类由自定义类加载器加载,优先使用1.69版本bcprov;原有功能由系统类加载器加载,使用1.54版本,实现完全隔离。

方案三:OSGi容器隔离(适合模块化架构项目)

如果项目本身是模块化架构,可将新SDK和1.69 bcprov打包为一个OSGi bundle,旧版本bcprov与原有功能作为另一个bundle。OSGi的模块隔离机制会保证不同bundle使用各自依赖的Jar版本,但该方案对项目架构改动较大,适合本身已使用OSGi的项目。


内容的提问来源于stack exchange,提问作者yang37

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:23:13