Gradle — scope зависимостей в опубликованных артефактах
При публикации Gradle-модуля в Maven-репозиторий scope зависимостей маппится в POM иначе, чем он работает локально.
Маппинг Gradle → Maven POM
| Gradle scope | Maven POM scope | Видимость для потребителя |
|---|---|---|
api | compile | compile + runtime |
implementation | runtime | только runtime |
compileOnly | — (не попадает в POM) | невидима |
runtimeOnly | runtime | только runtime |
compileOnlyApi | provided (в Gradle module metadata) | только compile |
Главный gotcha
implementation не скрывает зависимость от потребителя в опубликованном артефакте. Она попадает в POM как runtime и будет на runtime classpath всех потребителей.
implementation скрывает зависимость только на этапе компиляции у потребителя (классы не видны в IDE, не компилируются напрямую), но в runtime JAR-ы присутствуют.
Когда это важно
Если библиотека A зависит от B через implementation, и сервис S подключает A — то B окажется в runtime classpath сервиса S. Это может привести к:
- Split package — если A и B содержат классы в одном Java-пакете
- Конфликтам версий — если B тянет несовместимые транзитивы
- Раздуванию classpath — ненужные JAR-ы в деплое
Чтобы зависимость не утекала
compileOnly— если зависимость нужна только для компиляции/генерации кода- Исключение из публикации через конфигурацию
maven-publish
Проверка
У потребителя проверить транзитивы:
./gradlew :module:dependencies --configuration runtimeClasspath | grep "<имя-зависимости>"