如何进行网站开发,开发区人才,logo设计网站平台,浙江网站建设2019独角兽企业重金招聘Python工程师标准 看着简单而又复杂的pom.xml文件#xff0c;看似熟悉#xff0c;当自己编写的时候觉得简单#xff0c;但是看人家项目的时候又觉得复杂的很#xff0c;现在我们一起来分析这个pom文件。 Maven的坐标为各种构件引入了秩… 2019独角兽企业重金招聘Python工程师标准 看着简单而又复杂的pom.xml文件看似熟悉当自己编写的时候觉得简单但是看人家项目的时候又觉得复杂的很现在我们一起来分析这个pom文件。 Maven的坐标为各种构件引入了秩序任何一个构件都必须明确的定义自己的坐标maven的坐标包括如下的元素 groupId: 定义当前Maven项目隶属的实际项目 artifactId: 该元素定义实际项目中的一个Maven项目或模块 version: 该元素定义Maven项目当前所处的版本 packaging: 该元素定义Maven项目的打包方式 classifier: 该元素用来帮助定义构建输出的一些附属构件 注groupId、artifactId、version、packaging是必须定义的classifier是不能被直接定义的因为附属构件不是项目直接默认生成的而是由附加的插件帮助生成的。 元素详解 根元素project下的dependencies元素详解 dependencies可以包含一个或者多个dependency元素以声明一个或多个项目依赖, 其包含的元素 groupId、artifactId、version依赖的基本坐标对于任何一个依赖来说基本的坐标是最重要的Maven是根据坐标来找到需要的依赖 type: 依赖的类型 scope: 依赖的范围 optional: 标记依赖是否可选(参见可选性依赖) exclusions: 用来排除传递性依赖(参见依赖的传递性) 依赖范围详解 Maven在编译项目主代码的时候需要使用一套classpath Maven在编译和执行测试的时候会使用另外一套classpath Maven在实际运行项目的时候又会使用一套classpath 依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系 Maven的6种依赖范围 compile: 编译依赖范围(默认)对于编译、测试、运行三种classpath都有效 test: 测试依赖范围 只对测试classpath有效。典型范例Junit provided: 已提供依赖范围 对于编译和测试classpath有效但在运行时无效。典型范例servlet-api runtime: 运行时依赖范围 对于测试和运行classpath有效但在对编译主代码时无效。典型范例JDBC system: 系统依赖范围 import: (maven2.0.9及以上): 导入依赖范围它不会对三种实际的classpath产生影响 依赖范围(Scope)对于编译classpath有效对于测试classpath有效对于运行时classpath有效例子compileYYYspring-coretestYjunitprovidedYYservlet-apiruntimeYYJDBC驱动实现systemYY本地的Maven仓库之外的类库文件 了解了依赖的基本元素和依赖范围之后我们会发现在我们项目中经常会出现一些默认的配置问题导致编译和运行失败的情况现在让我们来学习如何解决这些问题首先要了解一下依赖的传递性 传递性依赖和依赖范围 简单的说一般项目中出现问题多数是因为重复的引用或者引用了较低版本的依赖或者是他们的依赖范围发生了变化。 举个例子来理解传递性依赖 我们创建了一个Maven Project-----learnDependency然后我们引入了spring-core这个依赖然后我们打开spring-core的 pom.xml发现spring-core也有自己的依赖commons-logging而且该依赖没有声明依赖范围那么默认的就是 compile所以这时我们就可以说commons-logging也是learnDependency的一个依赖这时我们就将这种依赖称之为传递 性依赖commons-logging是learnDependency的一个传递性依赖。有了传递性依赖我们就可以在使用的时候不去考虑我们引入的 依赖到底是否需要其它依赖和是否引入多余的依赖Maven 会解析各个直接依赖的pom将必要的间接依赖引入到项目中。 细说传递性依赖 假设A依赖于BB依赖于C那么我们就说A对于B是第一直接依赖B对于C是第二直接依赖A对于C是传递性依赖。 因为依赖是有依赖范围的那么对于这种传递性依赖Maven又是如何界定其依赖范围的呢 当第二直接依赖的范围是compile的时候传递性依赖的范围与第一直接依赖的范围一致 当第二直接依赖的范围是test的时候依赖不会得以传递 当第二直接依赖的范围是provided的时候只传递第一依赖范围也为provided的依赖且传递性依赖的范围同样是provided 当第二直接依赖的范围是runtime的时候传递性依赖的范围与第一直接依赖的范围一致但compile除外此时传递性依赖范围为runtime compiletestprovidedruntimecompilecompileruntimetesttesttestprovidedprovidedprovidedprovidedruntimeruntimeruntime 左侧第一列表示第一直接依赖范围最上面一行表示第二直接依赖 optional: 有时候我们不想让依赖传递那么可配置该依赖为可选依赖将元素optional设置为true即可。 在我们了解了Maven强大的依赖机制之后我们开始解决问题 常见问题一依赖的重复引入 之前说过Maven可以有效的解决依赖的重复引入问题但是为什么我们在项目还会出现这类问题呢先让我们来看一下Maven是如何处理重复引入问题的 情景一我们在项目中分别引入了2个依赖A和BA又依赖的CC又依赖了DB也依赖了D但是这个时候C依赖的D和B依赖的D的版本是不同的 项目----A---C----D 项目----B---D 也就是说当前项目引入了2次D依赖那么这时Maven将采用第一原则路径最近原则 情景二我们在项目中分别引入了2个依赖A和B而A和B又都引入了C但是此时A依赖的C和B依赖的C版本是不一致的那么这个时候Maven如何处理呢 这时第一原则已经不起作用了 在Maven2.0.8及之前的版本中 和 Maven2.0.9之后的版本Maven对于这种情况的处理方式是不一致的 确切的说 在Maven2.0.8及之前的版本中Maven究竟会解析哪个版本的依赖这是不确定的 在Maven2.0.9之后的版本中制定了第二原则第一声明者优先 就是说它取决于在POM中依赖声明的顺序 这个问题就说明了为什么我们常常遇到的可以正常运行的项目然后我们增加了一个看似无关的依赖然后项目就出现了错误就是这个传递性依赖搞的鬼 还要补充说明的一种情况是可选依赖 为什么会有可选依赖呢是因为某一个项目实现了多个特性但是我们在面向对象的设计中有一个原则叫单一职责性原则就是强调在一个类只有一项职责而不是糅合了太多的功能所以一般这种可选依赖很少会出现。 常见问题二默认引入的依赖----第二直接依赖的版本过低或者依赖了不稳定的快照 这个问题我们在开发中也经常遇到在某个第二直接依赖中引入了1.0版本但是我们现在想使用2.0版本这时我们要如何解决 引入一个名词排除依赖也可以叫替换依赖 想实现依赖排除然后替换成自己想要的依赖这时我们要用到的一个配置是exclusions 和exclusion我们可以使用这一元素声明排除依赖然后显示的声明我们想要的依赖在exclusions中可 以声明一个或多个exclusion来排除一个或多个传递性依赖。 注声明exclusion的时候只需要声明groupId和artifactId就能唯一定位依赖图中的某个依赖。 A ------- B ------×----C(version1.0) | | C(version2.0) 常见问题三解决重复的配置 我们在开发中也经常遇到这样的情况比如在使用spring framework的时候他们都是来自于同一个项目的不同模块因此这些依赖的版本都是相同的而且在将来升级的时候这些版本也会一起被升级这时 Maven又提供了一种解决方案------使用properties元素定义Maven属性然后引用。 示例 properties springframework.version2.5.6/springframework.version
/properties 这个时候我们就可以在声明依赖的时候使用${springframework.version}来替换具体的版本号 dependency groupIdorg.springframework/groupId artifactIdspring-context-support/artifactId version${springframework.version}/version
/dependency 如何正确的优化依赖 首先我们必须要对maven的依赖处理方式了然于胸然后我们就可以去除多余的依赖显示的声明必要的依赖保证每个构件都只有唯一的版本在依赖中存在 使用命令来查看当前项目的已解析依赖 mvn dependency : list 经过Maven解析之后就会构成一个依赖树 也可以使用命令查看当前项目的依赖树 mvn dependency : tree 使用命令分析当前当前项目的依赖 mvn dependency : analyze 该命令执行结果的两个重要部分 Used undeclared dependencies: 表示项目中使用到的但是没有显示声明的依赖 Unused declared dependencies: 表示项目中未使用的但显示声明的依赖 注dependency : analyze只会分析编译主代码和测试代码需要用到的依赖一些执行测试和运行时需要的依赖它无法发现。 对于项目中的最佳实践需要自己多多的尝试或者看别人的一些分享这样对于开发效率会有很大的帮助当然在项目开发的过程中不断的优化和调整这种方法也未尝不可。 转载于:https://my.oschina.net/u/2418042/blog/491698