gradle中compile、api、provided、implementation

本文深入解析Gradle中compile、api、provided、implementation的区别与应用场景,包括它们如何影响编译过程和依赖管理,以及在不同场景下的优缺点。

一、gralde中compile,api,provided,implementation的区别:

  1. compile ‘com.android.support:appcompat-v7:23.4.0’
  2. provided ‘com.squareup.dagger:dagger-compiler:1.2.1’(网络下载)
  3. provided fileTree(include: ‘*.jar’, dir: ‘…/…/…/core/Base/Gdroid/libs’)(本地路径)
  4. compile files(‘libs/picasso-2.4.0.jar’)
  5. compile project(’:androidPullToRefresh’)
  • compile是从repository(默认是jCenter())里下载一个依赖包进行编译并打包。

  • provided只提供编译支持,但是不会写入apk。比如我在编译的时候对某一个jar文件有依赖,但是最终打包apk文件时,我不想把这个jar文件放进去,可以用这个命令。

  • compile files是从本地的libs目录下寻找picasso-2.4.0.jar这个文件进行编译并打包。类似的命令有compile fileTree(dir: 'libs', include: '*.jar')意思是将libs目录下所有jar文件进行编译并打包。 compile project是将另一个module(等同eclipse中的library库文件)进行编译并打包。

  • api 指令 :完全等同于 compile指令,没区别,你将所有的compile改成api,完全没有错。

注:gradle tools升级到3.0.0以上,compile关键字 已经明确写明废弃了(api关键字的作用等同于之前的compile),但是google官方文档上说“还会保留一段时间,直到下个比较大的gradle tools版本发布”。所以现在仍然使用compile,不会报错。

implementation说明:

implementation指令:这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。

implementation的“访问隔离”只作用在编译期

implementation的“访问隔离”只作用在编译期。什么意思呢?如果lib C 依赖了lib A 2.0版本,lib B implementation依赖了lib A 1.0版本:

  • 那么编译期,libC 可访问2.0版本的libA
    ,libB可访问1.0版本的libA。但最终打到apk中的是2.0版本(通过依赖树可看到)。

  • 在运行期,lib B 和lib C都可访问lib
    A的2.0版本(因为apk的所有dex都会放到classLoader的dexPathList中)。

使用implementation有什么好处

  • 如果项目中有很多级联的工程依赖,比如上图中lib A B C的依赖是工程依赖。如果使用的依赖方式是compile/api,那么当lib A接口修改后重新编译时,会重新编译libA B C(即使lib C中并没有用到修改的libA的接口)。如果使用implementation依赖,因为“编译期隔离”的原因,不相关的lib就不会进行重新编译。

  • 如果项目中都是aar依赖,编译减少时长这个优点就没有了(因为aar已经是编译好的字节码了)。那么还有什么用呢?还是以上图为例。之前我们都是compile依赖,如果lib A已经依赖了lib B,那么在libC的build.gradle中就不用写lib A的依赖了。但这样会有问题:

    1. 我从lib C的build.gradle的依赖列表中不能完整的知道libC都需要依赖哪些lib。
    2. 假设这么一种情况,我知道项目中的依赖的libA的最高版本是2.0,那么app运行时就是使用的这个2.0版本的libA。这时候我需要打一个libC的aar。lib C如果通过compile传递依赖了libA,因此从lib C的build.gradle中不知道lib C 编译时依赖的是哪个版本的lib A。如果libC 打aar(编译)时,依赖的仍然libA 1.0,可能这个aar就有问题了。
<think>好的,我现在需要帮助用户解决两个问题:Java中的NoSuchFieldError错误,以及如何在非Gradle项目中创建Gradle项目。首先,我需要回顾之前的对话和用户提供的引用内容,确保解决方案的连贯性和准确性。 首先看第一个问题:Java的NoSuchFieldError。根据用户提供的引用和之前的回答,这个错误通常是由于JDK版本与Lombok不兼容引起的,特别是在升级到JDK21后,旧版Lombok无法访问内部API的qualid字段。用户之前已经得到了一些解决方案,比如升级Lombok版本、处理依赖冲突、清理构建缓存等。现在用户可能希望更详细的步骤或者确认这些步骤是否适用于他们的特定情况,比如在非Gradle项目中。 第二个问题是如何将非Gradle项目转换为Gradle项目。用户可能有一个基于Maven或其他构建工具的项目,现在想迁移到Gradle。需要提供创建Gradle项目的步骤,包括初始化构建脚本、迁移依赖、配置插件等。同时需要确保用户理解Gradle的基本结构和命令。 在处理第一个问题时,需要强调检查Lombok版本是否至少为1.18.30,并确认JDK版本兼容性。可能还需要指导用户如何排除依赖冲突,特别是在非Gradle项目中,比如Maven项目中的依赖排除。清理构建工具缓存也是关键步骤,需要具体说明如何在不同IDE中操作,比如IntelliJ或Eclipse。 对于第二个问题,即创建Gradle项目,可能需要分步骤说明如何从零开始初始化Gradle项目,或者如何将现有的Maven项目转换为Gradle。重点包括安装Gradle、生成build.gradle文件、迁移依赖项、处理项目结构差异等。同时要提醒用户注意构建脚本中的插件和仓库配置,以及如何运行Gradle命令。 需要确保回答结构清晰,步骤详细,并且语言简洁易懂。用户可能对构建工具迁移不太熟悉,所以每个步骤都需要明确的操作示例,比如如何编写build.gradle文件,如何排除依赖等。此外,相关问题部分需要涵盖用户可能遇到的后续疑问,比如如何验证Gradle配置是否正确,或者如何处理迁移过程中的常见错误。 最后,要确保引用之前的回答内容,保持一致性,并确认所有建议都适用于用户的具体情况,特别是非Gradle项目部分。可能需要提醒用户根据项目类型(如Maven)进行相应的调整,并注意不同构建工具之间的差异。</think>### Java的`NoSuchFieldError`错误解决与Gradle项目迁移指南 --- #### 一、`java.lang.NoSuchFieldError: JCImport qualid`错误解决方案 **问题根源**:该错误是由于JDK版本升级(如JDK21)后,Lombok旧版本无法访问Java编译器内部API的`qualid`字段[^1][^2][^3]。以下是具体修复步骤: --- ##### **1. 升级Lombok版本** - **非Gradle项目(如Maven)**: 修改`pom.xml`中Lombok依赖至**1.18.30及以上**: ```xml <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.32</version> <scope>provided</scope> </dependency> ``` **验证**:执行`mvn dependency:tree | grep lombok`确认版本生效[^1]。 ##### **2. 排除依赖冲突** - 若项目中其他库间接引入旧版Lombok,需显式排除: ```xml <dependency> <groupId>其他依赖组</groupId> <artifactId>其他依赖</artifactId> <exclusions> <exclusion> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclusion> </exclusions> </dependency> ``` ##### **3. 清理构建缓存** - **Maven项目**:删除`target`目录并执行: ```bash mvn clean install ``` - **IDE操作**: - IntelliJ:`File → Invalidate Caches / Restart` - Eclipse:`Project → Clean` ##### **4. 检查JDK兼容性** - **Lombok 1.18.30+**支持JDK17~21,确保环境变量指向兼容JDK版本[^3]: ```bash java -version ``` --- #### 二、非Gradle项目迁移为Gradle项目 **适用场景**:将Maven/Ant项目转换为Gradle项目,需以下步骤: --- ##### **1. 初始化Gradle项目** 1. **安装Gradle**: - 下载并配置环境变量(参考[Gradle官方文档](https://gradle.org/install/))。 - 验证安装: ```bash gradle -v ``` 2. **生成Gradle构建脚本**: 在项目根目录执行: ```bash gradle init --type pom # 若原项目为Maven,自动转换pom.xml为build.gradle ``` ##### **2. 手动迁移依赖(可选)** - **`build.gradle`示例**: ```groovy plugins { id 'java' id 'org.springframework.boot' version '3.2.0' } repositories { mavenCentral() } dependencies { implementation 'org.projectlombok:lombok:1.18.32' annotationProcessor 'org.projectlombok:lombok:1.18.32' // 其他依赖... } ``` ##### **3. 处理构建差异** - **资源目录**:Gradle默认资源路径为`src/main/resources`,需与原项目结构对齐。 - **插件配置**:添加Spring Boot插件或其他必要插件: ```groovy plugins { id 'io.spring.dependency-management' version '1.1.4' } ``` ##### **4. 执行构建** ```bash gradle build # 编译项目 gradle run # 运行应用 ``` --- #### 三、技术原理 - **NoSuchFieldError本质**:JDK21修改了`com.sun.tools.javac`内部API,旧版Lombok通过反射访问的`qualid`字段被移除[^3]。 - **Gradle迁移逻辑**:通过`gradle init`解析原有构建文件(如`pom.xml`),生成等效的Gradle配置。 --- #### 相关问题 1. **如何验证Gradle构建文件是否正确?** - 运行`gradle tasks`查看任务列表,或`gradle dependencies`检查依赖树。 2. **Gradle与Maven依赖声明有何区别?** - Maven使用XML,Gradle使用Groovy/Kotlin DSL,语法更简洁,例如`implementation`替代`<scope>compile</scope>`。 3. **JDK21是否完全兼容Spring Boot 3.x?** - Spring Boot 3.2+官方支持JDK21,需搭配Lombok 1.18.30+[^2]。 4. **迁移Gradle后如何保留Maven构建?** - 保留`pom.xml`,Gradle与Maven可并存,但需避免依赖版本冲突。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值