Ivy 的主要概念

依赖解析器(Dependency Resolver)

        依赖解析器是ivy里一个可插拔的类,主要用来找到依赖组件的ivy file,下载依赖的组件。“下载”的概念比较广泛:组件可以在web服务器或者本地文件系统。这时候的下载其实就是将文件从库里转存到ivy缓存中。此外,resolver的责任还有找到ivy文件并且下载组件,帮助实现不同的解析策略。正如你所见,依赖解析器可以理解为用来描述库的类。


模块配置说明(Module configurations explained

      配置是Ivy的重要部分,当你定义一个使用或者构建模块的方法时,你可以定义在某个配置里的模块要发布哪些组件,你也可以定义这个配置里都需要哪些依赖关系。

       此外,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)

    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

  


转载于:https://my.oschina.net/u/134516/blog/192921

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值