1.5.2 Apache Maven
- 在企业应用的多个项目中使用Ant,对可维护性有很大的影响。灵活性带来了许多由项目间拷贝产生的重复代码。Maven团队认识到标准化项目布局和统一构建生命周期的必要性。Maven选择约定优于配置的思想,这意味着它为你的项目配置和行为提供了有意义的默认值。项目自然而然就知道去哪些目录寻找源代码以及构建运行时有哪些task去执行。如果你的项目遵从默认值,那么只需要写几行XML就可以建立一个完整的项目。另外Maven也拥有为应用产生包含Javadoc在内的HTML格式项目文档的能力。
- Maven的核心功能可以通过开发定制的插件来扩展。Maven的社区非常活跃,几乎支持构建的每个方面,从集成其他工具到生成报告,你都能找到合适的插件。如果找不到满足需求的插件,你也可以自己去写。
标准布局
- 通过引入一个默认的项目布局,Maven确保每个拥有Maven知识的开发人员可以立刻知道去哪里找什么类型的文件。例如,Java应用程序源代码的目录是src/main/java。所有默认的目录都是可配置的。图1.12展示了一个Maven项目的默认布局。
构建生命周期
- Maven基于构建生命周期的思想。每个项目都确切知道有哪些步骤去执行构建、打包和发布应用程序,包括如下功能:
- 编译源代码
- 运行单元测试和集成测试
- 组装工件(例如,JAR文件)
- 将工件部署到本地仓库
- 将工件发布到远程仓库
- 在构建生命周期中每个步骤都称作一个
阶段(phase)
。这些阶段会被有序地执行。当在命令行中运行构建时,你想知道执行的阶段是固定的。假设你调用打包这个阶段,Maven会自动确定它所依赖的阶段如编译源代码和运行测试事先被执行。图1.13展示了Maven构建所预定义的阶段和它们执行的顺序。
依赖管理
- 在Maven项目中,所需要的外部依赖库都在构建脚本中定义。例如没如果项目需要Hibernate,那么你可以在依赖配置块中简单地定义它的独立工件坐标,比如组织名、工件名和版本。下面的代码片段展示了如何声名一个4.1.7 Finial版本的Hibernate核心库:
- 在运行时,声名的类库和它们的传递依赖会由Maven的依赖管理器下载,保存到本地地缓存中,这样你的构建就可以使用它们(例如,编译源代码)。Maven预配置从Maven Central下载依赖。接下来构建会从本地缓存中重用已经存在的工件,因此不用再连接Maven Central。Maven Central是Java社区中最流行的二进制工件仓库。图1.14展示了Maven工件的获取过程。
- Maven中的依赖管理不仅限于外部库。你也可以将其他Maven项目定义为依赖。这种需求出现的原因是软件分解成了多个模块,每个模块都是完成某项功能的组件。图1.15展示了一种传统的三层结构的模块化架构,在这个例子中,表现层包含了在页面渲染数据的代码,业务层是真实的业务对象,而集成层则从集成库中获取数据。
构建脚本样例
- 下面的清单展示了一个Maven构建脚本样例,名字是pom.xml,它实现了和Ant构建脚本相同的功能。记住,在这里要遵循默认约定,所以Maven会去src/main/java目录中寻找源代码,不是src。
缺点
- 和Ant一样,也要知道Maven的缺点:
- Maven推荐一个默认的结构和生命周期,常常会太过限制,也许不适合你的项目需求。
- 为Maven写定制的扩展过于累赘。你需要去学习Mojos(Maven的内部扩展API),如何提供一个插件描述符(又是XML),以及相关的特殊注解,以便提供扩展实现所需要的数据。
- Maven早期的版本(低于2.0.9)会自动尝试更新它们自己的核心插件,例如,将单元测试的支持插件升级到最新版本。这可能会导致脆弱和不稳定的构建。
1.5.3 对下一代构建工具的需求
- 在上面的小节中,我们了解了Ant和Maven工具的特性,以及它们的优势和缺点、很明显,你常常需要在选择构建工具时妥协于它们所支持的功能。要么你选择完全灵活且可扩展,但很难实现项目标准化,有唯一公式化代码,并且没有依赖管理支持的Ant,要么选择Maven,他能提供约定优于配置的方式和无缝的依赖管理器集成,但过于限制思维和拥有臃肿的插件系统。
- 如果一个工具工具能够折中,是不是很棒?羡慕的一些特性时一个演变的构建工具应该提供的:
- 具有表达性、声明式、可维护的构建语言。
- 标准化的项目布局和生命周期,但是具有完全的灵活性和对默认设置的完全可配置性。
- 拥有易用且灵活的方式去实现定制逻辑。
- 支持构建由多项目组成的项目结构。
- 支持依赖管理
- 能很好地集成和迁移现有的构建基础设施,包括能够引入现有的Ant构建脚本和可以将现有的Ant或Maven逻辑转换成其自身规则集的工具。
- 强调可扩展性和高效率的构建。如果你的项目需要长时间构建(比如2小时或更长),这一点是很重要的,某些大型的企业级项目就是这样。
- 本书会向你介绍一个工具,它提供了这些很棒的特性,它的名字叫作gradle。我们会一起学习如何使用Gradle和探索它能够提供的所有优点。
1.6小结
- 对于开发和测试人员来说,没有项目自动化的工作,都是重复、单调和易犯错的。伴随软件交付过程中的每一步一一从源代码编译到打包软件,再到发布至测试和产品环境一一都必须手动操作,项目自动化帮你消除手动操作介入的负担,让你的团队更有效率,带你进入到一个一键式和故障安全的软件发布过程。
- 在本章,我们了解了不同类型的项目自动化一按需构建,预定构建和触发构建一履盖了各种特殊用例。你应该了解到不同类型的项目自动化是不相互排斥的。实际上,它们是互相补充的。
- 项目构建工具是项目自动化的一个关键因素。它允许你声明一系列有序的规则,允许你在初始化构建时执行。通过分析构建工具的内部原理,我们讨论了构建工具的活动组件。构建引擎(构建工具的可执行度)处理构建脚本中预定义的规则集,并将它翻译成为可执行的任务。每个任务也许需要输入数据。最终,产生构建的输出依赖管理器是构建工具架构中的一个可选组件,它允许你声明项目正常运行时所需要的外部库。
- 通过深入了解两个流行的Java构建工具:Ant 和 Maven的实现方式,我们看到了构建工具的具体特性。Ant提供了一种非常灵活且通用的方式来定义构建逻辑, 但是没有对标准化项目提供指导或者有意义的默认任务,以便可以在项目中重复使用。它也没有提供一个开箱即用的依赖管理器,需要自己去管理外部依, Maven 则正好相反,它遵循约定优于配置的原则,支持有意义的默认配置和标准的构建生命周期。 Maven的内置特性支持对外部库和直接对 Maven项目的自动化依赖管理但 Maven的败笔却落在定制逻辑和非约定项目的结构和任务的易扩展性上。你知道,一个高级的构建工具需要在灵活性和可配置约定上折中,这样才能满足现代化软件顶目的需求。
- 在下一章中,我们会来了解 Gradle是如何满足构建需求的