Gradle子项目间依赖声明方法咨询(附示例代码)
嘿,我来帮你搞定Gradle多项目里依赖声明的正确姿势,先看看你现有配置里的几个小问题,再给你一套标准的实现方案~
先聊聊你现有配置的可优化点
- sourceSets配置:你把
srcDirs设为['./']会把项目根目录下所有文件都当作源码,这不符合Gradle的默认规范,除非你有特殊的目录结构需求,不然建议用默认的src/main/java结构,能减少很多不必要的配置。 - 依赖配置过时:你用了
compile project(':p2'),但Gradle从5.x版本开始就废弃了compile这个配置,现在推荐用implementation(如果不需要把依赖暴露给上层项目)或者api(如果依赖需要被上层项目感知)。 - Jar的Class-Path配置问题:你当前的
configurations.runtime.files.collect { it.name }.join('')有两个问题:一是runtime配置已经被废弃,应该用runtimeClasspath;二是直接拼接文件名的话,当子项目的Jar不在同一目录时会找不到依赖,而且多项目构建里通常不需要手动设置Class-Path,Gradle会自动处理依赖传递,或者用更便捷的插件来打包可执行Jar。
正确的多项目依赖配置方案
首先得明确你的项目结构,多项目构建必须在根目录的settings.gradle里声明子项目,假设你的结构是这样的:
根项目/ ├── settings.gradle ├── p1/ (Java应用项目) │ └── build.gradle └── p2/ (Java库项目) └── build.gradle
1. 根目录的settings.gradle
先注册两个子项目:
include ':p1', ':p2'
2. Java库项目(p2)的build.gradle
你用java-library插件是完全正确的,这个插件专门为库项目设计,提供了api和implementation来控制依赖的可见性:
plugins { id 'java-library' } // 除非你必须用自定义源码目录,否则注释掉这段,用默认的src/main/java结构 // sourceSets { // main { // java { // srcDirs = ['./'] // } // } // } // 库项目一般不需要配置Jar的Class-Path和Main-Class,除非有特殊需求 // jar { // manifest.attributes( // // 这里不需要设置Main-Class,库项目没有主入口 // ) // } // 如果你的库有外部依赖,比如Guava,按需选择api或implementation // dependencies { // api 'com.google.guava:guava:32.1.3-jre' // api会把依赖暴露给依赖此库的项目 // // implementation 'xxx' // implementation的依赖仅在库内部可见 // }
3. Java应用项目(p1)的build.gradle
推荐用application插件,它比单纯的java插件更适合应用项目,能自动处理主类配置、依赖打包和运行任务:
plugins { id 'java' id 'application' // 强烈推荐,简化可执行Jar的配置 } // 同样,优先用默认源码目录,特殊情况才自定义 // sourceSets { // main { // java { // srcDirs = ['./'] // } // } // } // 声明对p2的依赖,用implementation就足够了(应用项目不需要把p2的依赖暴露给其他项目) dependencies { implementation project(':p2') } // 用application插件直接指定主类,自动处理Class-Path application { mainClass = 'Main' // 替换成你的主类全限定名 } // 如果你一定要手动配置Jar(不推荐,用application插件的distZip/distTar更方便),可以这么修改: // jar { // manifest { // attributes( // 'Main-Class': 'Main', // // 用runtimeClasspath替代过时的runtime,并且要注意路径匹配 // 'Class-Path': configurations.runtimeClasspath.files.collect { "../${it.name}" }.join(' ') // // 路径需要根据最终Jar的存放位置调整,这里假设p2的Jar在同一父目录下 // ) // } // } // 要是想打包成单个包含所有依赖的可执行Jar,可以用Shadow插件 // plugins { // id 'com.github.johnrengelman.shadow' version '8.1.1' // } // shadowJar { // mainClass = 'Main' // }
一些最佳实践
- 尽量遵循Gradle的默认项目结构,减少自定义配置的复杂度,默认结构是
src/main/java放源码,src/main/resources放资源文件。 - 彻底抛弃过时的配置:
compile、runtime、testCompile等,改用implementation、api、runtimeOnly、testImplementation等。 - Java应用优先用
application插件,它提供了run任务直接运行项目,还能生成包含依赖的分发包;如果需要单个可执行Jar,用Shadow插件是最便捷的方式。
内容的提问来源于stack exchange,提问作者Paulo Marcio
相关产品推荐
相关产品推荐

