依赖解析器(Dependency Resolver)php
依赖解析器是ivy里一个可插拔的类,主要用来找到依赖组件的ivy file,下载依赖的组件。“下载”的概念比较普遍:组件能够在web服务器或者本地文件系统。这时候的下载其实就是将文件从库里转存到ivy缓存中。此外,resolver的责任还有找到ivy文件而且下载组件,帮助实现不一样的解析策略。正如你所见,依赖解析器能够理解为用来描述库的类。html
模块配置说明(Module configurations explained ) java
配置是Ivy的重要部分,当你定义一个使用或者构建模块的方法时,你能够定义在某个配置里的模块要发布哪些组件,你也能够定义这个配置里都须要哪些依赖关系。web
此外,ivy的依赖关系是在模块上来表述而不是在组件上,重要的是可以定义哪些依赖的配置在你定义的模块配置里是须要的(it is important to be able to define which configurations of the dependency are required in the configuration you define of your module.)这就是所谓的配置映射(configuration mapping)正则表达式
若是你用的只是简单的模块,不想考虑配置问题,你不须要担忧。它们依然存在,由于ivy的工做离不开配置。更多的时候你什么都不用声明,ivy认为在全部配置里你模块的组件都要发布,一样在全部配置里任何依赖配置都是须要的。可是当你想要把模块里的东西拆分或者更多的控制文件的发布以及更好的依赖解决方案,配置会知足你大多数需求算法
变量(Variables) apache
Ivy变量能够惭怍ant的属性,用法也相似。特别是,你能够在配置文件里用属性标签来加载包括ivy变量和值的属性文件。缓存
ant属性和ivy变量的主要区别是ivy变量能够被覆写(可是ant 属性不能够),而且它们是定义在不一样的环境里。服务器
若是你从ant调用ivy,全部的ant属性都会在配置结束的时候导入到ivy变量里。这意味着若是你在嗲用配置以后定义了一个ant属性,这个属性是不不能当作ivy变量来用的。另外一方面,ivy变量是不会输出到ant里,所以当你在ivy里定义了ivy变量,就不要再尝试将它们用做ant属性。
网络
要使用ivy变量,你只须要遵循和ant属性同样的语法就能够了:${变量名}
最后,知道变量替换的时间也很重要。变量替换会尽快完成,这意味着当ivy遇到一个引用变量,它会尝试去替换,前提是这个变量已经定义好了。所以,稍后的任何改变都不会更改已经替换了的值。
此外,在ant环境里,一堆变量会默认经过ant属性文件加载机制设置(事实上他们首先被做为ant属性加载,而后做为ivy变量导入,参考 Ant Tasks),甚至在ant变量里它们也会在加载的时候替换,有效的阻止了一些变量经过ivysetings.properties被彻底覆写。 某些变量只能经过ant属性来覆写就是由于这个。
另外,理解ivy变量和ivy 模式标记(pattern tokens)也很是重要
模式(Patterns)
Ivy 模式用于不少依赖解析器和ivy task中,是ivy工做的一种简单方法。
举个例子,你能够给文件系统的依赖解析器配置一种模式来找到相关的组件,这个模式能够像这样写:
myrepository/[organisation]/[module]/[type]s/[artifact]-[revision].[ext] 这个模式代表,咱们使用的存储库是一个名叫myrepository的目录。在这个目录中,咱们有以咱们须要寻找的模块的组织名命名的目录,接着是每一个模块的目录,每一个目录都是以模块名命名的。而后在模块目录里咱们能够找到每一个组件类型(jars,wars,ivy...)的目录,在这些目录里咱们能够找到以id命名的组件,后面是连字符,修订版本,点号以及组件的扩展名。并不难理解。
再多点解释,一种模式是由一组标记组成,当匹配特定的组件或模块时这些标记会被实际的值取代。这些标记和变量不一样由于它会被不一样的组件以不一样的值取代,而变量一般是相同的值。
你能够将变量和标记混合起来用在模式中:
${repository.dir}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]这些标记是否可用取决于模式再哪里用(例如,它会被组件或者模块来评估吗). 当前全部可用的标记以下:
[organisation] 组织名
[orgPath] (since 2.3) "."被替换为"/"的组织名。可用来配置相似maven2的存储库
[module] 模块名
[branch] 分支名
[revision] 修订版
[artifact] 组件名或id
[type] 组件类型
[ext] 组件的扩展名
[conf] 配置文件名
[originalname] (since 1.4) 原始组件名(包括后缀)
since 1.3, 模式中能够有可选的部分。若是某个标记没有定义就不会有输入,也避免了只有一个空的标记留在那里。圆括号用来界定可选部分,而且括号中只能有一个标记。也就是说,若是你用"("和")"将一个标记括起来,若是标记没有定义,那么这个括号内的其余字符也会被忽略。例如, 假设一个模式是"abc(def[type]ghi)", 若是type="jar" 那么替换后的模式是abcdefjarghi,若是type=null 或者"", 替换后的模式就是abc。
更实际的例子如: [artifact](-[revision]).[ext],能够陪陪到myartifact-1.0.jar 和 myartifact.jar。这个在你须要控制组件名字的时候尤为有用
since 1.4 扩展属性能够在模式里用做其余标记
最新策略(Latest Strategy)
Ivy常常须要知道两个版本中哪个是比较新的,它使用最新策略概念来达到此目的。事实上,有不少种方法能够界定最新版本。捏能够选择已存在或者插入你本身的。
在知道哪个版本比较新以前,ivy须要可以比较一个模块的几个修订版。这样ivy就须要拿到一个目录下的文件一个列表,它使用依赖解析器来实现。在考虑为何ivy不能获得你的最新修订版以前,先检查你用的依赖解析器是否可最新修订版匹配。
最后,为了获得一个模块的多个修订版,大多数时候你须要在你的模式中用[revision]标记,使ivy得到全部和该模式匹配的文件,无论它的修订版是多少。而后最新策略才能肯定哪一个版本是最新的。
Ivy 有三个内置的最新策略:
latest-time
比较修订版日期来肯定哪个是最新的。就针对性而言这一般是比较好的策略,但其缺点是在计算距离较远的存储库的时候会很耗成本。例如当你用ivyrep时,ivy必须问http服务器每一个ivy文件的日期才能知道哪个是最新的。
latest-revision
将修订版当字符串来比较,使用和php 版本比较功能相接近的算法。该算法考虑一些文本的特殊含义。例如,这个策略中按时间顺序1.0-dev1->1.0-alpha1->1.0-rc1->1.0->1.0.1.
latest-lexico
将修订版当字符串来比较 ,按字母顺序(java字符串比较所使用的顺序)
冲突管理器(conflict Manager)
冲突管理器能够在有冲突的模块版本中选择保存一个或多个版本。若是一系列修订版对应于同一个模块,例如相同的组织或者模块名,就说它们有冲突。
可用的冲突管理器列表见冲突管理器配置
模式匹配器(Pattern matcher)
在不少地方ivy使用模式去匹配一组对象。例如你在使用模式匹配声明依赖关系时能够一次排除多个模块。Ivy使用可插拔的模式匹配器去陪陪这些对象名。有3个是默认定义好的:
exact: 只使用按字符匹配
regexp :since 1.4,可使用java模式类支持的正则表达式
glob: 可使用相似Unix的全局匹配器,例如 元字符“*”匹配任意字符,?配置一个字符。注意,该匹配器只有在jakarta oro 2.0.0在你的classpath中时才可用
扩展属性(Extra attributes)
since 1.4 ivy xml文件里的不少标签都是可被扩展属性扩展的。概念很是简单:若是你须要更多的信息来定义你的模块,你能够添加你想要的属性,而且你能够像其余属性同样在你的模式中访问它。
since 2.0 你能够而且也建议你在扩展属性中使用xml 命名空间。使用Ivy扩展命名空间是添加你本身扩展属性最简单的方法。这里有一个ivy文件,里面的“color”属性设置为blue:
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra"> <info organisation="apache" module="foo" e:color="blue" status="integration" revision="1.59" /> </ivy-module>
这样一来,当你声明foo的依赖时你必须使用这些扩展属性。这些扩展属性会被用来当作模块的标识符,相似org名字和修订版本。
<dependency org="apache" name="foo" e:color="blue" rev="1.5+" />
你也能够像这样定义你的存储库模式:
${repository.dir}/[organisation]/[module]/[color]/[revision]/[artifact].[ext]
注意,在模式中你必须使用未经修饰的属性名(没有命名空间作前缀)
若是你不想使用xml命名空间,这个是能够的,可是你须要禁止ivy文件校验,由于你的文件再也不符合官方ivy定义。
校验码(Checksums)
since 1.4 Ivy容许使用校验码,也称为摘要(digests),来验证下载文件的的正确性。
目前Ivy支持md5和sha1算法。使用md5和sha1的配置须要全局或者依赖解析器完成。全局地,使用ivy.checksums变量列出须要完成的校验(只支持md5和sha1)。在每一个解析器里,你可使用校验码属性覆写全局设置。
设置是一个用逗号分开的校验码算法列表 。在校验期间(下载的时候),使用第一个找到的校验码去作校验,就这样。这意味着,若是你用了“sha1,md5”设置,会比较下载文件的sha1和设置的sha1,若是比较结果正确,那个这个文件就会被认为是正确的。若是没有找到sha1文件,会继续找md5文件,若是都没有找到,就不作校验。
在发布期间,全部列出来的校验码算法都会被计算而且上传。
校验码算法默认是 "sha1,md5"。若是你想更改这个默认设置,你能够设置变量ivy.checksums。所以,要想禁止校验码校验你只须要将ivy.checksums设置为“”就能够了。
事件和触发器(Events and Triggers)
since 1.4 当Ivy执行依赖解析和其余任务时,它会在最重要的步骤以前和以后触发事件。你可使用Ivy API来监听这些事件,或者你甚至能够注册一个触发器在特定事件发生的时候去执行一个特定的行为,这是一个很是强大且灵活的功能,它使你能够在一个依赖被解析以前执行构建,或者精确的追踪在依赖解析的过程当中到底发生了什么,等等。
循环依赖(Circular Dependencies)
since 1.4 循环依赖能够是直接的或间接地。例如,A 依赖A,这个循环依赖,A依赖B,B又依赖A,这也是循环依赖。
在1.4以前,循环依赖会引发Ivy错误。自从1.4以后,Ivy能够经过循环依赖策略找到循环依赖是可配置的。可用的三个内置策略:
ignore:循环依赖只表示为冗余信息(circular dependencies are only signaled in verbose messages)
warn:除了会表示为警告外,和ignore同样.
error:当发现循环依赖时中止依赖解析
缓存和变动管理(Cache and Change Management)
Ivy很是依赖于本地缓存,一次来避免常常性的访问远程库,也节省了不少网络带宽和时间。
缓存类型:
Ivy缓存由两个不一样的部分组成:
存储库缓存(the repository cache):是Ivy存储从模块库里下载来的数据的地方,以及一些关于这些组件的原数据信息,例如原始的位置。这部分缓存是能够共享的,可是你的有一个很是合适的锁策略(lock strategy)
解析缓存(the resolution cache):这部分缓存用来存储解析数据,Ivy用来重复使用解析过程的结果。这部分缓存会在每次新的解析执行以后被覆写,不该该被多进程同时使用。
虽然始终只有一个解析缓存,你能够定义多个存储库缓存,每一个解析器可使用单独的缓存。
变动管理
为了优化依赖解析和缓存的使用方式,Ivy默认假定修订版不会改变。所以一旦Ivy模块(元数据和组件)在缓存中,它就信任缓存而且不会再去查询存储库。这个优化在不少状况下很是有用,而且不会引发问题,前提是你遵循这个惯例:修订版永远不会变。除了性能,还有其余很是好的理由去遵照这个原则。然而,根据你当前的构建系统和依赖管理策略,你可能更喜欢时不时更新你的模块。有两种改变须要考虑:
原数据变动:
由于模块的提供者并不会像关注API或者行为那样常常考虑模块原数据(即便他提供了模块原数据),这个常常发生,咱们被不得不更新模块原数据:某个依赖被忘记,或者另一个丢失,... 在这种状况下能够在依赖管理器里设置 checkModified="true"来解决。这个标识告诉Ivy去检查与缓存中的数据相比模块元数据是否被修改。Ivy首先在须要的时候检查要下载存的储库中元数据的最后修改的时间戳,而后在须要的时候进行更新。
组件变动
有些人,尤为是时从maven 2 转过来的,喜欢使用一个特殊的修订版来处理常常更新的模块。在maven 2中被称为SNAPSHOT版本,有争论说这样能够帮助节省磁盘空间,在开发期间生成大量中间构建物中只保存一个版本。
Ivy用“变动修正版”(changing revision)概念来支持这种方法。一个变动修正版就是:Ivy认为通过一段时间组件会改变的一个修订版。为了处理这个,你能够指定一个依赖做为依赖标识变动(?you can either specify a dependency as changing on the dependency tag),或者在解析器中使用变动模式(changingPattern)和变动匹配器(changingMatcher)属性来讲明哪一个修订版或者那组修订版应该被认为会改变。
一旦Ivy知道了某个版本会改变,它会遵照这个原则来避免过多的检查你的存储库:若是模块的原数据没有变,那么整个模块(包括组件)都么有变。尽管模块的描述文件改变了,它也会检查模块的发布数据去看看是不是新发布的相同修订版。这时若是发布日期改变了,它会去检查组件的最后修改时间,而后作相应的下载。
所以若是你想使用变动修订版,使用publish任务区发布你的模块,它会注意更新发布日期,全部的事情都会顺利进行。还有记得在你的解析器里设置checkModified="true"!
路径处理(Paths handling)
做为一个依赖管理工具,Ivy有不少文件相关的操做,大多数时候会使用到路径或者路径模式来定位文件系统中的文件。这些路径能够是相对或绝对路径。咱们建议一直使用绝对路径,这样你就不用但系相对路径的基础是什么。Ivy提供了一些变量,能够用来做为你绝对路径的基础。例如,Ivy有基础目录的概念,基本上和Ant同样。你能够用ivy.basedir变量来访问这个基础目录。所以若是你的路径时这样的:${ivy.basedir}/ivy.xml, 你就有一个绝对路径,在设置文件里,也有一个称为ivy.settings.dir的变量指向设置件的目录位置,是的定义到这个文件的相对路径很是容易。
若是你真的想使用相对路径,实际用来定位文件的基础路径依赖于相对路径在哪里定义:
在Ivy文件里,路径相对于文件Ivy文件自己(在Ivy文件里惟一可能的路径就是包含配置声明)
在设置文件中,包含文件的路径(也就是属性文件的加载和内容设置)是相对于设置文件的目录位置。其余全部的路径必须是绝对的除非有明确说明
在Ivy的Ant任务和Ivy参数或选项中,路径是相对于Ivy的基础目录,当从Ant调用时,就是你的Ant basedir