依赖管理
其实这个标签揭示了jar的查找坐标:groupId、artifactId、version。
一般而言,我们可以到私服上输入artifactId进行搜索,或者到http://search.maven.org/、http://mvnrepository.com/上进行查找确定坐标。
version分为开发版本(Snapshot)和发布版本(Release),那么为什么要分呢?
在实际开发中,我们经常遇到这样的场景,比如A服务依赖于B服务,A和B同时开发,B在开发中发现了BUG,修改后,将版本由1.0升级为2.0,那么A必须也跟着在POM.XML中进行版本升级。过了几天后,B又发现了问题,进行修改后升级版本发布,然后通知A进行升级…可以说这是开发过程中的版本不稳定导致了这样的问题。
Maven,已经替我们想好了解决方案,就是使用Snapshot版本,在开发过程中B发布的版本标志为Snapshot版本,A进行依赖的时候选择Snapshot版本,那么每次B发布的话,会在私服仓库中,形成带有时间戳的Snapshot版本,而A构建的时候会自动下载B最新时间戳的Snapshot版本!
Q3:既然Maven进行了依赖管理,为什么还会出现依赖冲突?处理依赖冲突的手段是?
依赖的版本?
首先来说,对于Maven而言,同一个groupId同一个artifactId下,只能使用一个version!
根据上图的依赖顺序,将使用1.2版本的jar。
现在,我们可以思考下了,比如工程中需要引入A、B,而A依赖1.0版本的C,B依赖2.0版本的C,那么问题来了,C使用的版本将由引入A、B的顺序而定?这显然不靠谱!如果A的依赖写在B的依赖后面,将意味着最后引入的是1.0版本的C,很可能在运行阶段出现类(ClassNotFoundException)、方法(NoSuchMethodError)找不到的错误(因为B使用的是高版本的C)!
这里其实涉及到了2个概念:依赖传递(transitive)、Maven的最近依赖策略。
依赖传递:如果A依赖B,B依赖C,那么引入A,意味着B和C都会被引入。
Maven的最近依赖策略:如果一个项目依赖相同的groupId、artifactId的多个版本,那么在依赖树(mvn dependency:tree)中离项目最近的那个版本将会被使用。(从这里可以看出Maven是不是有点小问题呢?能不能选择高版本的进行依赖么?据了解,Gradle就是version+策略)
现在,我们可以想想如何处理依赖冲突呢?
想法1:要使用哪个版本,我们是清楚的,那么能不能不管如何依赖传递,都可以进行版本锁定呢?
使用 [这种主要用于子模块的版本一致性中]
想法2:在依赖传递中,能不能去掉我们不想依赖的?
使用 [在实际中我们可以在IDEA中直接利用插件帮助我们生成]
想法3:既然是最近依赖策略,那么我们就直接使用显式依赖指定版本,那不就是最靠近项目的么?
使用
Q4:引入依赖的最佳实践,提前发现问题!
在工程中,我们避免不了需要加一些依赖,也许加了依赖后运行时才发现存在依赖冲突在去解决,似乎有点晚!那么能不能提前发现问题呢?
如果我们新加入一个依赖的话,那么先通过mvn dependency:tree命令形成依赖树,看看我们新加入的依赖,是否存在传递依赖,传递依赖中是否和依赖树中的版本存在冲突,如果存在多个版本冲突,利用上文的方式进行解决!
Q5:Maven规范化目录结构
简单Java工程目录结构
这里需要注意2点:
第一:src/main下内容最终会打包到Jar/War中,而src/test下是测试内容,并不会打包进去。
第二:src/main/resources中的资源文件会COPY至目标目录,这是Maven的默认生命周期中的一个规定动作。(想一想,hibernate/mybatis的映射XML需要放入resources下,而不能在放在其他地方了)
Q6:Maven的生命周期
Maven生命周期
我们只需要注意一点:执行后面的命令时,前面的命令自动得到执行。
实际上,我们最常用的就是这么几个:
clean:有问题,多清理!
package:打成Jar or War包,会自动进行clean+compile
install:将本地工程Jar上传到本地仓库
deploy:上传到私服
Q7:关于scope依赖范围
既然,Maven的生命周期存在编译、测试、运行这些过程,那么显然有些依赖只用于测试,比如junit;有些依赖编译用不到,只有运行的时候才能用到,比如mysql的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。
总结来说:
compile:默认的scope,运行期有效,需要打入包中。
provided:编译期有效,运行期不需要提供,不会打入包中。
runtime:编译不需要,在运行期有效,需要导入包中。(接口与实现分离)
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以扫码领取!!!!
最后
针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
-
Android前沿技术大纲
-
全套体系化高级架构视频
Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可免费领取!
11249798304)]
Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可免费领取!