compileOnly 在 Gradle 中等效于 Maven 的 provided:仅参与编译,不打包进产物,不传递依赖,适用于 Servlet API、Lombok 等编译期所需、运行时由容器或 JDK 提供的库。

Gradle 中用 compileOnly 可以实现类似 Maven 的 provided 作用域效果:该依赖仅参与编译,不打包进最终产物(如 JAR/WAR),也不参与运行时类路径。
compileOnly 的核心行为
compileOnly 是 Gradle Java 插件提供的标准配置(Configuration),它只影响编译期 classpath,对 runtime、test、fat jar 等均无影响。它不会传递依赖,也不会出现在构建产物的 META-INF/MANIFEST.MF 或 lib/ 目录中。
- 适用于 Servlet API、Lombok、注解处理器(如 MapStruct、QueryDSL)等只在编译时需要、运行时由容器或 JDK 提供的库
- 与
implementation或api不同,compileOnly声明的依赖不会被下游模块继承 - 不能在源码中用于运行时反射调用或 new 实例——因为运行时确实不存在该类
基本写法(Groovy DSL)
在 build.gradle 中直接添加:
dependencies {
compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
compileOnly 'org.projectlombok:lombok:1.18.30'
}
注意:Gradle 7.0+ 已弃用 compileOnly 的旧别名(如 providedCompile),应统一使用 compileOnly。
立即学习“Java免费学习笔记(深入)”;
对应 Kotlin DSL 写法
若使用 build.gradle.kts:
dependencies {
compileOnly("javax.servlet:javax.servlet-api:4.0.1")
compileOnly("org.projectlombok:lombok:1.18.30")
}
也可配合 configurations 进一步约束,比如禁止意外引入到 runtime:
configurations.compileOnly {
extendsFrom(configurations.implementation.get())
}
但通常无需此操作,因为 compileOnly 默认已隔离。
验证是否生效
可通过以下方式确认依赖未被打包:
- 执行
./gradlew dependencies --configuration compileClasspath,查看compileOnly是否出现在编译 classpath 中 - 执行
jar tf build/libs/*.jar | grep servlet,确认javax.servlet-api类未出现在 JAR 包内 - 运行应用时若抛出
NoClassDefFoundError,说明你误用了compileOnly声明了运行时必需的类——此时应改用runtimeOnly或implementation


















