着色scala(jar)库的依赖关系

时间:2015-08-05 19:30:06

标签: java scala jar sbt packaging

我想分发一个我创建的库的jar,其中包含所有依赖项。但是,我想避免与采用项目的依赖项版本冲突。

我认为maven shade可以做到这一点,但我找不到使用Scala / SBT做到这一点的方法。我发现OneJar然而从我的实验中它似乎只适用于可执行文件。

我怎么能实现这个目标?

谢谢!

3 个答案:

答案 0 :(得分:2)

Proguard可以在jar中重命名包并混淆代码。它有点复杂,但你可以用它实现你的目标。 sbt-proguard插件已被主动维护

您也可以查看类似帖子的答案:

maven-shade like plugin for SBT

<强>更新

来自版本i

sbt-assembly插件似乎有shading ability

答案 1 :(得分:2)

您可以使用自己的类加载器执行此操作。

classLoader:
编写一个类加载器,使用重写从不同的类加载器加载类文件。

例如,您可以在获取资源时将库作为前缀添加到类路径中。

我使用此teqnuiqe创建了一个类加载器。 https://github.com/espenbrekke/dependent/blob/master/src/main/java/no/dependent/hacks/PathRewritingClassLoader.java

它替换URLClassLoader中的方法findClass,其中一个添加前缀。

protected Class<?> findClass(final String name) throws ClassNotFoundException {
    Class result;
    try {
        result = (Class)AccessController.doPrivileged(new PrivilegedExceptionAction() {
            public Class<?> run() throws ClassNotFoundException {

// This is where the prefix is added:
                String path = PathRewritingClassLoader.this.prefix + name.replace('.', '/').concat(".class");
                Resource res = PathRewritingClassLoader.this._ucp.getResource(path, false);
                if(res != null) {
                    try {
                        return PathRewritingClassLoader.this._defineClass(name, res);
                    } catch (IOException var4) {
                        throw new ClassNotFoundException(name, var4);
                    }
                } else {
                    return null;
                }
            }
        }, this._acc);
    } catch (PrivilegedActionException var4) {
        throw (ClassNotFoundException)var4.getException();
    }

    if(result == null) {
        throw new ClassNotFoundException(name);
    } else {
        return result;
    }
}

我们还必须重写资源加载

@Override
public URL getResource(String name){
    return super.getResource(prefix+name);
}

以下是它的使用方法:

_dependentClassLoader = new PathRewritingClassLoader("private", (URLClassLoader)DependentFactory.class.getClassLoader());
Class myImplementationClass=_dependentClassLoader.loadClass("my.hidden.Implementation");

建立你的jar:
在您的构建中,将所有库和私有类放在所选前缀下。在我的gradle构建中,我有一个简单的循环收集所有依赖项。

task packageImplementation {
dependsOn cleanImplementationClasses

doLast {
    def paths = project.configurations.runtime.asPath
    paths.split(':').each { dependencyJar ->
        println "unpacking" + dependencyJar

        ant.unzip(src: dependencyJar,
                dest: "build/classes/main/private/",
                overwrite: "true")
        }
    }
}

答案 2 :(得分:0)

您是否尝试过sbt-assembly插件?它在冲突的情况下有一套合并策略,并且有很好的入门指南。

相关问题