Kotlin 简介
Kotlin (科特林)是一个用于现代多平台应用的静态编程语言 ,由 JetBrains开发。
Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。
除此之外Kotlin还可以编译成二进制代码直接运行在机器上(例如嵌入式设备或[ iOS](https://baike.baidu.com/item/ iOS/45705?fromModule=lemma_inlink))。
Kotlin已正式成为Android官方支持开发语言。
2011年7月,JetBrains推出Kotlin项目,这是一个面向JVM的新语言,它已被开发一年之久。JetBrains负责人Dmitry Jemerov说,大多数语言没有他们正在寻找的特性,Scala除外。但是,他指出了Scala的编译时间慢这一明显缺陷。Kotlin的既定目标之一是像Java一样快速编译。 2012年2月,JetBrains以Apache 2许可证开源此项目。
Jetbrains希望这个新语言能够推动[IntelliJ IDEA](https://baike.baidu.com/item/IntelliJ IDEA/9548353?fromModule=lemma_inlink)的销售。
Kotlin v1.0于2016年2月15日发布。这被认为是第一个官方稳定版本,并且JetBrains已准备从该版本开始的长期向后兼容性。
在[Google I/O](https://baike.baidu.com/item/Google I%2FO/7108524?fromModule=lemma_inlink) 2017中,Google宣布在Android上为Kotlin提供一等支持。 [3]
设计目标
创建一种兼容Java的语言
让它比Java更安全,能够静态检测常见的陷阱。如:引用空指针
让它比Java更简洁,通过支持variable type inference,higher-order functions (closures),extension functions,mixins and first-class delegation等实现。
让它比最成熟的竞争对手Scala语言更加简单。 [3]
开放源码
其基础编译器(他们将其改为kompiler——开创了一系列以K字打头的用语——甚至连 contributors这类词他们也用改成了kontributors)可以被独立出来并嵌入到 Maven、Ant 或 Gradle 工具链中。这使得在 IDE 中开发的代码能够利用已有的机制来构建,从而尽可能的减少了在新环境中使用所受的干预,哪怕与那些没有安装 Kotlin 插件的开发人员一起合作项目也没有问题。
The IntelliJ Kotlin 插件扩展了 Java 编译器使得 Kotlin 代码能够得以编写、编译和调试。除此之外,关于基本的 Java 集合,已经有编写好的帮助函数,可以更顺畅地衔接将在 Java 8 中出现的集合扩展。
有两篇文章对 Kotlin 与 Java 以及 Kotlin 与 Scala 分别进行了比较,对各自特性和异同进行了对比。即便 Scala 可能还是更为强大些,Kotlin 还是尝试着提供比 Java 更好的函数、模式匹配、空指针预防和泛型。该语言同时也支持特征(traits)和模式匹配。
Kotlin 插件在当前版本的[ IntelliJ ](https://baike.baidu.com/item/ IntelliJ /3306058?fromModule=lemma_inlink)和 Eclipse 中均已能使用。
2、Gradle与maven的对比
Gradle作为基于Groovy语言的构建工具,与Gradle相比,ant显得冗长复杂,maven显得有些局促落后,但Gradle基于DSL语法,特点明显。 简洁、灵活、可读性强
1 .基本构成信息
maven使用. pom文件,
gradle使用. gradle文件基于XML,gradle使用Groovy,gradle使用maven需要固定配置的groupId、artfactId、软件包等基本参数
2 .依赖管理
Gradle的jar软件包管理支持maven的存储库方法和Ant的yedts方法。 因为maven的存储库非常成熟,所以Gradle与存储库兼容,所以非常方便。 定义maven的存储库: maven local ():maven本地库、mavenCentral ) ) : maven远程库、mavenRepo urls:自定义库路径
maven使用组id、名称和版本来查找与配置的资料档案库中指定的依
赖关系相关的Jar包。 虽然Gradle的生命周期更为复杂,但它也支持依赖于Maven的构建生命周期。 compile、runtime、testCompile和testRuntime分别支持项目各个阶段的依赖关系。 它还简化了maven的配置命令
3 .多项目管理
在实际使用中,大多数情况下,需要管理的不仅仅是一个项目。 maven使用依赖、继承和配置的概念,为父模块指定自己的子模块,并提供插件、配置信息等各子模块共有的资源。 通过将封装模块与实现具体功能的模块分开的方法,管理多个项目。 Gradle在这方面更明确,划分更明确,也更容易学习Gradle的多个项目管理。 在eclipse中安装Gradle插件后,创建新的Gradle项目,选择flat-Java-multi项目时,生成的项目就是多个项目管理的一个例子。
Gradle通过settings.Gradle文件指定项目的子项目,在构建初始化阶段(Initialization ),Gradle基于settings.Gradle文件指定哪个子项目初始化每个子项目的项目对象。由于有很多项目配置,因此我们将简要介绍常见的配置共享和配置独占。
多模块项目的Gradle目录结构
示例:我的示例项目demo,我需要有一个common模块用于公用代码,一个rest模块用于提供rest接口,rest依赖common,如果用gradle构建,目录树会是这样:
demo
├── build.gradle -- 全局配置
├── settings.gradle -- 全局配置
├── common -- 子模块1目录
│ └── build.gradle -- 子模块1配置
├── rest -- 子模块2配置
│ └── build.gradle -- 子模块2配置
...
“所有项目”属性。 返回这个项目对象及其所有子项目。
subProjects属性。 返回这个项目的所有子项目。
项目' : su B-project-name ' )来设置相应子项目的配置。
configure(subprojects.findall ) it.name.contains('XXX'} )会来寻找符合您需求的子专案。
将您自己的配置添加到子项目的build.gradle文件中。
Gradle项目管理工具
基于Groovy的特定领域语言来声明项目设置
Gradle安装(Windows)
1.下载解压版
- 版本列表:https://services.gradle.org/distributions/
- v6.5:https://downloads.gradle-dn.com/distributions/gradle-6.5-bin.zip(用迅雷下载可能会快些)
2.配置环境变量
- gradle_home
- 变量名:GRADLE_HOME
- 变量值:D:\tool\gradle-7.5.1-all\gradle-7.5.1(gradle安装目录)
- path(编辑)
- 变量名:Path(编辑)
- 变量值:%GRADLE_HOME%\bin(增加)
- gradle_user_home(在远程仓库下载的jar包保存到该路径下)
- 变量名:GRADLE_USER_HOME
- 变量值:D:\dev\maven\repository
D:\dev\jdk\java-1.8.0-openjdk-1.8.0.312-2.b07.dev.redhat.windows.x86_64
D:\tool\Java\jdk-11.0.6
3.配置init.gradle
在gradle安装目录\init.d
目录下,创建init.gradle文件,
allprojects{
repositories {
def REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public/'
all { ArtifactRepository repo ->
def url = repo.url.toString()
if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) {
project.logger.lifecycle 'Repository ${repo.url} replaced by $REPOSITORY_URL .'
remove repo
}
}
maven {
url REPOSITORY_URL
}
}
buildscript {
repositories {
def REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public/'
all { ArtifactRepository repo ->
def url = repo.url.toString()
if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) {
project.logger.lifecycle 'Repository ${repo.url} replaced by $REPOSITORY_URL .'
remove repo
}
}
maven {
url REPOSITORY_URL
}
}
}
}
初始化基本配置:配置远程仓库地址(gradle没有自己的仓库,使用的是maven的仓库)
4.验证是否配置成功
cmd输入命令:
gradle -v
Gradle本地仓库
可能有很多人在纠结这个 Gradle 能不能像 maven 一样手动修改本地仓库,答案当然是肯定的,
而且很简单,只需要在环境变量里面做个配置即可如下图:
即添加一个名称为 GRADLE_USER_HOME ,值是你想放gradle仓库的地方即可。
GRADLE_HOME=D:\tool\gradle-7.5.1-all\gradle-7.5.1
GRADLE_USER_HOME= D:\dev\maven\repository
GRADLE_USER_HOME= D:\dev\maven\graddleRep
spring-boot-dependencies.version = 2.1.12.RELEASE
//先从本地仓库寻找,本地仓库没有再从中央仓库寻找
mavenLocal();
类似Maven的dependencyManagement方式实现依赖管理
Spring开发了一个类似Maven的依赖关系管理功能的Gradle插件( )。
引入插件
plugins {
id "io.spring.dependency-management" version "1.0.8.RELEASE"
}
依赖管理配置
你有两个选项来配置依赖项管理:
- 使用插件的DSL来直接配置依赖项
- 导入一个或者多个已经存在的Maven bom文件
依赖项的管理默认被, 应用到所有的配置或者一个或者多个指定的配置中。
依赖项管理DSL
使用:
分隔符的配置方式:
dependencyManagement {
dependencies {
dependency 'org.springframework:spring-core:4.0.3.RELEASE'
}
}
通过group
,name
,version
进行指定配置:
dependencyManagement {
dependencies {
dependency group:'org.springframework', name:'spring-core', version:'4.0.3.RELEASE'
}
}
通过上面两种方式中的任意一种进行了管理配置之后,在需要引入spring-core的包时,就可以通过如下方式配置依赖:
dependencies {
compile 'org.springframework:spring-core'
}
这样一个依赖管理配置就完成了。
依赖集配置
如果对于多个模块具有相同的group和version的依赖配置,你可以使用依赖集进行配置。
这样你就只需要指定统一的group和version,而依赖模块不需要再额外指定。
如下所示:
dependencyManagement {
dependencies {
dependencySet(group:'org.slf4j', version: '1.7.7') {
entry 'slf4j-api'
entry 'slf4j-simple'
}
}
}
排除依赖(exclusion)
可以使用Maven的Exclusios语义进行依赖项的排除。
对单个依赖项进行排除:
dependencyManagement {
dependencies {
dependency('org.springframework:spring-core:4.0.3.RELEASE') {
exclude 'commons-logging:commons-logging'
}
}
}
也可以对依赖集的entry中进行排除:
dependencyManagement {
dependencies {
dependencySet(group:'org.springframework', version: '4.1.4.RELEASE') {
entry('spring-core') {
exclude group: 'commons-logging', name: 'commons-logging'
}
}
}
}
导入Maven Bom
插件允许你导入已经存在的Maven Bom来使用其依赖的关系管理:
dependencyManagement {
imports {
mavenBom 'io.spring.platform:platform-bom:1.0.1.RELEASE'
}
}
dependencies {
compile 'org.springframework.integration:spring-integration-core'
}
这个配置会将Spring框架的Bom的依赖应用到当前的项目
本地Module library依赖
//module需要在项目根目录下的settings.gradle中通过include引入
implementation project(':librarydict')
2.本地二进制library依赖:jar和aar
本地的jar和aar需要放在module的libs文件夹下,通过这种方式依赖的弊端时不知道jar和aar的版本号,如果要按照这种方式依赖,建议将jar/aar的名字加上版本信息,方便确认版本
依赖jar:
//可以一条依赖引入libs下所有的jar
implementation fileTree(dir:'libs',include:['*.jar'])
//也可以指定依赖某一个或几个jar
implementation files('libs/dict-v120.jar','libs/download-v151.jar')
引入远程maven仓库
//依赖明确的版本,标明group、name和version
implementation group:'con.android.demo',name:'library-dict',version:'1.2.0'
//通常按照如下方式简写即可
implementation 'com.android.demo:library-dict:1.2.0'
//也可以不知道版本,将version改为"+",当远程仓库有更新的版本后,构建时会拉取最新的版本。
//好处是可以始终依赖最新的library:弊端是有可能library的改动导致编译不过或者功能变更不稳定,因为每次都需要检查是否有最新版本,所以构建效率会低一些
implementation 'com.android.demo:library-dict:+'
修改gradle的镜像仓库
改单个项目
在项目的build.gradle文件中,修改repositories配置,
将mavenCentral()改为 maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}, 如:
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
}
更改所有项目
如果想一次更改所有的仓库地址,可以在 USER_HOME/.gradle/
文件夹下
添加 init.gradle
文件来配置,如:
allprojects{
repositories {
def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/'
all { ArtifactRepository repo ->
if(repo instanceof MavenArtifactRepository){
def url = repo.url.toString()
if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')) {
remove repo
}
}
}
maven {
url REPOSITORY_URL
}
}
}
修改Gradle本地仓库的位置 方法
Gradle的配置
可能有很多人在纠结这个 Gradle 能不能像 maven 一样手动修改本地仓库,答案当然是肯定的,而且很简单,只需要在环境变量里面做个配置即可。
即添加一个名称为 GRADLE_USER_HOME ,值是你想放gradle仓库的地方即可。
- 新建系统变量:
GRADLE_USER_HOME
D:\gradle\.gradle\
2.如下图:
补充说明一点 据说 Gradle有个 Daemon配置,开启这个配置能有效的提高编译速度,具体是不是这样我没有做过对比因为我安装了gradle后就配置了。。。
3.具体操作如下:
在咱们的gradle仓库.gradle目录下创建一个gradle.properties 文件 ,再打开该文件在其中添加如下语句保存即可:
org.gradle.daemon=true
就这样简单。
Gradle工程目录
gradle-demo
|---src
|---|---main
|---|---|---java(放置正式代码目录)
|---|---|---resources(放置正式配置文件目录)
|---|---|---webapp(放置页面元素)
|---|---test
|---|---|---java(放置单元测试代码目录)
|---|---|---resources(放置测试配置文件目录)
|---build.gradle
|---settings.gradle
groovy编程语言
Gradle在idea中使用
-
idea中,使用groovy语言编辑器,
Tools - Groovy Console
-
方法调用,省略分号,小括号
-
定义字符串,单引号定义普通字符串,双引号可以引用变量,三引号按格式定义字符串
输出
//介绍groovy编程语言
println("hello groovy"); // idea快捷键sout
println("hello groovy") // 可以省略最后的分号
println "hello groovy" // 可以省略括号
println 12 + ":" + 24
println 12 + 24
定义变量
// groovy 中定义变量
// def 是弱类型,groovy会自动根据情况来给变量赋予对应的类型
def foo = 18;
def bar = 疯狂创客圈
println foo;
字符串定义
方式1:单引号定义字符串
使用 '...'
单引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。
并且通过 str1.class 可以验证方式1输出的字符串类型就是 java.lang.String
方式2:双引号定义字符串
使用 "..."
双引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。
并且通过 str1.class 可以验证方式2输出的字符串类型就是 java.lang.String
str1 = '疯狂创客圈' // 定义普通字符串
str2 = "name:${str1}" //可以引用变量
str3 = '''name:xiaoming
age:18''' //按格式定义字符串
println str1
println str1.class
println str2
println str2.class //class org.codehaus.groovy.runtime.GStringImpl
通过上面的例子可以看出,通过在str2中拼接 ${变量/表达式}
之后输出的 class
类型不再是 java.lang.String
而是 org.codehaus.groovy.runtime.GStringImpl
很明显这个类型就是 GString 的实现类。
因此可以知道单引号和双引号定义的字符串的区别在双引号定义的字符串可以通过 $
进行扩展,而单引号定义的字符串是不可变的,因此不可以扩展。
方式3:三个单引号定义字符串
使用 '''...'''
双引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。
并且通过 str3.class 可以验证方式3输出的字符串类型就是 java.lang.String
str1 = '疯狂创客圈' // 定义普通字符串
//这里会有一个换行符号\n
def str5 ='''
疯狂创客圈 一个java 高并发研究社群
Hello 疯狂创客圈
疯狂创客圈
${str1} 是一个java 高并发研究社群
'''
println str5.class //class org.codehaus.groovy.runtime.GStringImpl
assert str5.startsWith("\n")//验证 str5 是以 \n 开头的
方式3对字符串的样式进行修改,例如换行,缩进。
方式4:三个双引号定义字符串
str1 = '疯狂创客圈' // 定义普通字符串
//这里会有一个换行符号\n
def str5 ="""
疯狂创客圈 一个java 高并发研究社群
Hello 疯狂创客圈
疯狂创客圈
${str1} 是一个java 高并发研究社群
"""
println str5
println str5.class //class org.codehaus.groovy.runtime.GStringImpl
assert str5.startsWith("\n")//验证 str5 是以 \n 开头的
定义一个集合类型
def list = ['a','b']
// 往list中添加元素
list.add("疯狂创客圈")
list.add("java高并发社群")
list << 'c'
// 取出list中第3个元素
println list.get(2)
定义一个map
def map = ['key1':'value1','key2':'value2']
// 向map中添加键值对
map.key3 = 'value3'
// 打印出key3的值
println map.get('key3')
闭包(无参数)
// groovy 中的闭包
// 什么是闭包?闭包其实就是一段代码块。在gradle中,我们主要是把闭包当参数来使用
// 闭包省略()
//plugins({
// id('java')
//})
//相当于
//plugins {
// id 'java'
//}
// 定义一个闭包
def b1 = {
println "hello b1"
}
// 定义一个方法,方法里面需要闭包类型的参数
def method1(Closure closure) {
//closure()
closure.call()
}
// 调用方法method1
method1(b1)
method1 b1
method1({
println "xiaoming"
})
method1 {
println "xiaoming"
}
闭包(有参数)
//定义一个闭包,带参数
def b2 = {
v ->
println "hello ${v}"
}
// 定义一个方法,方法里面需要闭包类型的参数
def method2(Closure closure){
//closure("xiaoma")
closure.call("xiaoma")
}
// 调用方法method2
method2 b2
method2 {
v ->
println "hello ${v}"
}
断言 assert
where = 疯狂创客圈
assert where == 疯狂创客圈
gradle构建脚本介绍
gradle构建脚本介绍(build.gradle)
两个重要的概念 project 和 task
任何一个Gradle构建都由一个或多个project组成,每个project包括许多的构建部分
每个project由一个或多个Task组成,每个Task表示在构建执行过程中的一个原子操作
构建Project完成后会生成一个jar或者war文件,构建过程中Gradle基于build.gradle实例化一个org.gradle.api.Project对象,并通过project变量来隐式的调用其成员变量
Project对象属性:project(隐式使用)、group、name、version、path、description、projectDir、buildDir、ant
其它常用配置:plugins(apply plugin)、dependencies、repositories、task、ext(gradle.properties 属性配置)
Gradle管理jar包
build.gradle文件的基本内容
plugins {
id 'java'
// web工程需要的插件
id 'war'
}
version '1.0-SNAPSHOT'
group 'xin.yangshuai'
sourceCompatibility = 1.8
/*
* 指定所使用的仓库
*/
repositories {
// Gradle没有自己的中央仓库
// 先从本地maven仓库寻找依赖的jar包,存在则直接使用本地maven仓库的jar
mavenLocal()
// 本地maven仓库没有则从远程仓库下载jar包,并保存到 环境变量GRADLE_USER_HOME 配置的路径下
// 设置maven仓库阿里镜像地址
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
// 配置使用Maven的中央仓库
mavenCentral()
}
/**
* 配置依赖的jar包
*/
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
/* web工程需要的jar包 */
compile group: 'org.springframework', name: 'spring-context', version: '5.0.2.RELEASE'
compile group: 'org.springframework', name: 'spring-web', version: '5.0.2.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '5.0.2.RELEASE'
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
providedCompile group: 'javax.servlet', name: 'jsp-api', version: '2.0'
}
配置gradle的repositories仓库
mavenLocal()的配置
- mavenLocal()表示使用本地maven仓库
- mavenCentral()使用maven中心仓库
- 使用阿里云(maven {url 'http://maven.aliyun.com/nexus/content/groups/public/'})#这个相当于使用自定义maven仓库地址的配置,可以是私服。
- JCenter是Goovy Grape内的默认仓库,Gradle内建支持jcenter()仓库,项目库打包成aar文件类似jar,只是多了res,lib文件的包,上传到jcenter后,可以很方面的在本地调用库文件
repositories {
mavenLocal()
// mavenCentral()
maven {url 'https://maven.aliyun.com/repository/public/';}
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}
gradle默认本地依赖存储位置
因为Gradle如果不配置环境变量,则会在用户目录下(在Windows下是C盘的目录)创建.gradle目录,并将下载的依赖文件保存在这个目录里。
如果不想使用缺省目录,则可以设置环境变量GRADLE_USER_HOME的路径,就可改变gradle的缓存目录。
使用maven本地仓库
#配置M2_HOME
#mavenLocal() 时Gradle默认会按以下顺序去查找本地的maven仓库:
# USER_HOME/.m2/settings.xml > M2_HOME/conf/settings.xml > USER_HOME/.m2/repository。
- 修改build.gradle文件,配置maven本地仓库
mavenLocal()
repositories {
mavenLocal()
}
-
使用maven本地仓库,需要告知gradle本地maven仓库的地址,配置
M2_HOME
环境变量,
M2_HOME /conf/settings.xml
中指定我们本地仓库的位置
- 变量名:M2_HOME
- 变量值:D:\tool\apache-maven-3.6.0(maven安装路径)
当我们使用maven本地仓库(mavenLocal())时,jar包会直接利用本地maven仓库,而不会去下载
注意: gradle寻找本地maven仓库位置的策略
USER_HOME /.m2/settings.xml` >> `M2_HOME/conf/settings.xml` >> `USER_HOME/.m2/repository
1、我们一般在
maven的安装目录/conf/settings.xml
(也就是我们配置的maven环境变量)中配置本地仓库位置,所以我们需要让gradle选择该路径,从而使用我们配置的maven本地仓库2、gradle先寻找
USER_HOME/.m2/settings.xml
,所以我们要删掉该文件(其实也可以将安装目录下的settings.xml复制过来)3、maven环境变量我们习惯配置成MAVEN_HOME,但是gradle寻找的是M2_HOME,所以我们需要配置M2_HOME环境变量
验证: 切换使用mavenCentral()和mavenLocal(),查看jar包引用地址
使用远程仓库
- 修改build.gradle文件,配置maven中央仓库
repositories {
mavenCentral()
}
- 当需要在远程仓库下载jar包时,会将jar包保存到
GRADLE_USER_HOME\caches\modules-2\files-2.1\
文件夹下,配置 GRADLE_USER_HOME 环境变量,也可以直接在idea中指定位置- 变量名:GRADLE_USER_HOME
- 变量值:D:\work\gradleCK
其它可用的远程仓库地址
repositories {
mavenLocal()
// 阿里
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
mavenCentral()
}
关于gradle中jar包引用的说明
如果我们在
repositories{}
中先配置mavenLocal()(maven本地仓库)
,再配置mavenCentral()(远程仓库)
,那么gradle引用jar的位置就会出现两个,如果本地maven仓库中存在则直接引用本地maven仓库中的jar包,
如果本地maven仓库中不存在,则会连接远程仓库地址,将jar包下载到gradle本地缓存地址,并且引用该地址下的jar包。
注意: gradle并不会向本地maven仓库中下载jar包,gradle缓存路径下的jar包与maven本地仓库中的jar包的格式也有区别。
参考:https://blog.csdn.net/feinifi/article/details/81458639
验证: 查看项目中不同jar包的引用地址(maven仓库中存在的jar包和不存在的jar包,观看其引用的地址)
gradle中jar包的依赖配置
jar包依赖方式
/**
* 配置依赖的jar包
* gradle工程所有的jar包的坐标都在dependencies属性内放置
* 每一个jar包的坐标都有三个基本元素组成 group,name,version
* 添加坐标的时候都要带上jar包的作用域
*/
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jar包的依赖范围(作用域)
jar包的依赖范围(作用域):
compile:编译阶段:主程序、测试程序均有效;运行阶段:均有效
providedCompile:编译阶段:主程序、测试程序均有效;运行阶段:均无效(依靠运行时环境提供的jar包)
runtime:编译阶段:主程序、测试程序均无效(无需依赖);运行阶段:均有效
testCompile:编译阶段:主程序无效,测试程序有效;运行阶段:均有效
testRuntime:编译阶段:主程序、测试程序均无效(无需依赖);运行阶段:测试程序有效
jar包依赖版本冲突默认解决方式
jar包依赖具有传递性
依赖jar包版本存在冲突解决方案:
maven:最短路径原则,先声明原则
gradle:选择最高版本
修改jar包依赖的配置策略
configurations.all {
resolutionStrategy {
// 配置后将不自动处理jar包版本冲突,可以与依赖的排除配合使用
failOnVersionConflict()
// 强制使用某个版本的jar包,覆盖依照gradle默认策略引用的jar包
force 'org.slf4j:slf4j-api:1.7.24'
}
}
直接在build.gradle中配置configurations.all{}
依赖的排除
dependencies {
compile(group: 'org.hibernate', name: 'hibernate-core', version: '3.6.3.Final') {
// 排除某个依赖,其中 module 相当于 jar包坐标中的 name
exclude(group: 'org.slf4j', module: 'slf4j-api')
}
}
任务(Task)的编写
任务(task)的主要操作动作
- dependsOn:依赖相关操作,定义任务时参数依赖、任务内部依赖、外部添加依赖
- doFirst:任务执行之前执行的方法
- doLast(<<(旧功能,不提倡)):任务执行之后执行的
task t1 {
doFirst {
println 't1 do first'
}
println 'hello t1'
doLast {
println 't1 do last'
}
}
// 参数依赖
task t2(dependsOn: 't1') {
// t2执行前操作
doFirst {
println 't2 do first'
}
println 'hello t2'
// t2 执行后操作
doLast {
println 't2 do last'
}
}
// 结论:在构建Project时,只执行直接定义在task下(非doFirst和doLast闭包中)的代码,有依赖也不会再次执行依赖的task
// 直接调用task时,只执行在doFirst或doLast闭包中的代码,并且会优先执行依赖的task的doFirst或doLast闭包中的代码
task t3 {
// 任务内部依赖
dependsOn 't1'
println 'hello t3'
doLast {
println 't3 do last'
}
}
task t4 {
doFirst {
println 't4 do first'
}
println 'hello t4'
}
// 外部添加依赖
t4.dependsOn 't1'
//动态任务
4.times {
val ->
task "task${val}" {
doFirst {
println "The task is task${val}"
}
println "hello task${val}"
}
}
task t5 {
// 给任务添加自定义属性
ext.myProperty = 'The property value'
doFirst {
println "t5 ${myProperty}"
}
println 'hello t5'
}
Gradle项目构建生命周期
Gradle项目构建生命周期
初始化阶段:
通过settings.gradle判断哪些项目需要初始化,加载所有需要初始化的项目的build.gradle文件并为每个项目创建project对象
配置阶段:
执行各项目下的build.gradle脚本,完成project的配置,并且构造task任务关系图以便在执行阶段按照依赖关系执行task中的配置代码(直接定义在task下的代码,配置阶段就需要执行)
执行阶段:
通过配置阶段的task图,按顺序执行需要执行的任务中的动作代码(任务调用才会执行的代码,定义在doFirst或doLast中的代码)
Gradle项目构建生命周期的钩子方法
我们可以直接覆写这些方法,在方法中加入我们自己的逻辑,(写在build.gradle或者settings.gradle中)
// 项目构建之前
gradle.settingsEvaluated {
println "初始化阶段0 settingsEvaluated"
}
gradle.projectsLoaded {
println "初始化阶段1 projectsLoaded"
}
// 配置阶段
gradle.beforeProject {
println "配置阶段0 beforeProject"
}
gradle.afterProject {
println "配置阶段1 afterProject"
}
gradle.projectsEvaluated {
println "配置阶段2 projectsEvaluated"
}
gradle.taskGraph.whenReady {
println "配置阶段3 taskGraph.whenReady"
}
// 执行阶段
gradle.taskGraph.beforeTask {
println "执行阶段0 taskGraph.beforeTask"
}
gradle.taskGraph.afterTask {
println "执行阶段1 taskGraph.afterTask"
}
gradle.buildFinished {
println "执行阶段2 buildFinished"
}
Gradle创建多模块项目
父模块有settings.gradle文件,子模块没有settings.gradle文件,
settings文件
settings中配置所拥有的子模块
rootProject.name = 'demo'
include 'service'
include 'app'
父模块build.gradle
父模块build.gradle中配置公用的信息,插件、依赖等
// 配置统一信息,包括root模块
allprojects {
// 统一引入 java 插件,并指定版本(注:不能将plugins {id 'java'} 直接挪到 allprojects 里面,变换一下形式)
apply plugin: 'java'
sourceCompatibility = 1.8
// 统一配置公共属性,例如:group、version
group 'xin.yangshuai'
version '1.0-SNAPSHOT'
}
// 子模块配置统一信息
subprojects {
// 配置公用的资源库
repositories {
mavenCentral()
}
// 配置公用的依赖
dependencies {
compile 'ch.qos.logback:logback-classic:1.2.2'
}
}
dependencies {
}
子模块build.gradle
子模块build.gradle中配置特有的信息
apply plugin: 'war'
//如果使用plugins引用插件,则buildscript必须放到plugins前面
buildscript {
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
jcenter()
}
dependencies {
classpath 'com.bmuschko:gradle-tomcat-plugin:2.5'
}
}
dependencies {
compile project(':core')
// providedCompile:只在编译时依赖,运行环境下不需要
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
}
常用的Gradle的5种依赖详解
依赖类型
dependencies DSL标签是标准Gradle API中的一部分,而不是Android Gradle插件的特性,所以它不属于android标签。
Gradle依赖有三种方式,如下面的例子:
apply plugin: 'com.android.application'
android { ... }
dependencies {
// Dependency on a local library module
implementation project(":mylibrary")
// Dependency on local binaries
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Dependency on a remote binary
implementation 'com.example.android:app-magic:12.3'
}
本地library模块依赖
implementation project(":mylibrary")
这种依赖方式是直接依赖本地库工程代码的,
需要注意的是,mylibrary的名字必须匹配在settings.gradle中include标签下定义的模块名字。
本地二进制依赖
implementation fileTree(dir: 'libs', include: ['*.jar'])
这种依赖方式是依赖工程中的 module_name/libs/目录下的Jar文件
注意Gradle的路径是相对于build.gradle文件来读取的,所以上面是这样的相对路径。
如果只想依赖单个特定本地二进制库,可以如下配置:
implementation files('libs/foo.jar', 'libs/bar.jar')
远程二进制依赖
implementation 'com.example.android:app-magic:12.3'
上面是简写的方式,这种依赖完整的写法如下:
implementation group: 'com.example.android', name: 'app-magic', version: '12.3'
group、name、version共同定位一个远程依赖库。
需要注意的点是,version 最好不要写成"12.3+"这种方式,除非有明确的预期,因为非预期的版本更新会带来构建问题。
远程依赖需要在repositories标签下声明远程仓库,例如jcenter()、google()、maven仓库等。
依赖配置
目前Gradle版本支持的依赖配置有:
- implementation、
- api、
- compileOnly、
- runtimeOnly
- annotationProcessor
已经废弃的配置有:
- compile、
- provided、
- apk、
- providedCompile。
此外依赖配置还可以加一些配置项,例如AndroidTestImplementation、debugApi等等。
常用的是implementation、api、compileOnly三个依赖配置,含义如下:
implementation
与compile对应,会添加依赖到编译路径,并且会将依赖打包到输出(aar或apk),
但是在编译时不会将依赖的实现暴露给其他module,也就是只有在运行时其他module才能访问这个依赖中的实现。
使用这个配置,可以显著提升构建时间,因为它可以减少重新编译的module的数量。
建议,尽量使用这个依赖配置。
api
与compile对应,功能完全一样,会添加依赖到编译路径,并且会将依赖打包到输出(aar或apk),
与implementation不同,这个依赖可以传递,
其他module无论在编译时和运行时都可以访问这个依赖的实现,也就是会泄漏一些不应该不使用的实现。
举个例子,
A依赖B,B依赖C,如果都是使用api配置的话,A可以直接使用C中的类(编译时和运行时),
而如果是使用implementation配置的话,在编译时,A是无法访问C中的类的。
compileOnly
与provided对应,
Gradle把依赖加到编译路径,编译时使用,不会打包到输出(aar或apk)。
这可以减少输出的体积,在只在编译时需要,在运行时可选的情况,很有用。
runtimeOnly
与apk对应,gradle添加依赖只打包到APK,运行时使用,但不会添加到编译路径。
这个很少使用。
annotationProcessor
与compile对应,用于注解处理器的依赖配置,
这个很少使用。
查看依赖树
可以查看单个module或者这个project的依赖,通过运行依赖的Gradle任务,如下:
-
View -> Tools Windows -> Gradle(或者点击右侧的Gradle栏);
-
展开 AppName -> Tasks -> android,然后双击运行AndroidDependencies。
运行完,就会在Run窗口打出依赖树了。
依赖冲突解决
随着很多依赖加入到项目中,难免会出现依赖冲突,出现依赖冲突如何解决?
定位冲突
依赖冲突可能会报类似下面的错误:
Program type already present com.example.MyClass
通过查找类的方式(command + O)定位到冲突的依赖,进行排除。
如何排除依赖
- dependencies中排除(细粒度)
compile('com.taobao.android:accs-huawei:1.1.2@aar') {
transitive = true
exclude group: 'com.taobao.android', module: 'accs_sdk_taobao'
}
- 全局配置排除
configurations {
compile.exclude module: 'cglib'
//全局排除原有的tnet jar包与so包分离的配置,统一使用aar包中的内容
all*.exclude group: 'com.taobao.android', module: 'tnet-jni'
all*.exclude group: 'com.taobao.android', module: 'tnet-so'
}
- 禁用依赖传递
compile('com.zhyea:ar4j:1.0') {
transitive = false
}
configurations.all {
transitive = false
}
还可以在单个依赖项中使用@jar标识符忽略传递依赖:
compile 'com.zhyea:ar4j:1.0@jar'
- 强制使用某个版本
如果某个依赖项是必需的,而又存在依赖冲突时,此时没必要逐个进行排除,可以使用force属性标识需要进行依赖统一。
当然这也是可以全局配置的:
compile('com.zhyea:ar4j:1.0') {
force = true
}
configurations.all {
resolutionStrategy {
force 'org.hamcrest:hamcrest-core:1.3'
}
}
- 在打包时排除依赖
先看一个示例:
task zip(type: Zip) {
into('lib') {
from(configurations.runtime) {
exclude '*unwanted*', '*log*'
}
}
into('') {
from jar
from 'doc'
}
}
代码表示在打zip包的时候, 会过滤掉名称中包含“unwanted”和“log”的jar包。
这里调用的exclude方法的参数和前面的例子不太一样,前面的参数多是map结构,这里则是一个正则表达式字符串。
也可以使用在打包时调用include方法选择只打包某些需要的依赖项:
task zip(type: Zip) {
into('lib') {
from(configurations.runtime) {
include '*ar4j*', '*spring*'
}
}
into('') {
from jar
from 'doc'
}
}
主要是使用dependencies中排除和全局配置排除。
参考
-
疯狂创客圈 JAVA 高并发 总目录
https://www.cnblogs.com/crazymakercircle/p/9904544.html
ThreadLocal(史上最全)
https://www.cnblogs.com/crazymakercircle/p/14491965.html -
3000页《尼恩 Java 面试宝典 》的 35个面试专题 :
https://www.cnblogs.com/crazymakercircle/p/13917138.html -
价值10W的架构师知识图谱
https://www.processon.com/view/link/60fb9421637689719d246739
4、架构师哲学
https://www.processon.com/view/link/616f801963768961e9d9aec8
5、尼恩 3高架构知识宇宙
https://www.processon.com/view/link/635097d2e0b34d40be778ab4
Kotlin 1.4 现已发布,专注于质量和性能 – Kotlin Blog | JetBrains .Kotlin官网.2020-08-17[引用日期2020-08-29]
6 Kotlin Programming Language .Kotlin[引用日期2018-02-02]
7 基于JVM的编程语言 Kotlin .开源社区网[引用日期2012-08-16]
8 IDEA下搭建Kotlin环境 .CSDN[引用日期2020-07-09]
9 Eclipse下搭建Kotlin开发环境 .CSDN.2016-02-18[引用日期2017-11-15]
10 Kotlin Programming Language .Kotlin语言官网[引用日期2021-02-22]
https://www.zhangshilong.cn/work/24556.html
https://blog.csdn.net/qq_41895810/article/details/120042035
https://blog.csdn.net/shuair/article/details/107319204
https://www.cnblogs.com/albertdale/p/14939529.html
https://blog.csdn.net/ywb201314/article/details/125716928
https://blog.csdn.net/qq_23085893/article/details/79633934
标签:依赖,最全,配置,jar,gradle,maven,Gradle,史上 From: https://www.cnblogs.com/crazymakercircle/p/16913023.html