(C5)Tapestry IoC:Tapestry IoC Configurations

本人翻译目的是用来学习Tapestry5的,共享出来希望大家批评指正。计划持续翻译。
chinajavawolf  
Tapestry IoC 配置
 
Tapestry IoC 的一个关键概念是分布配置。这个概念借鉴 Eclipse Plugin API Tapestry5 IoC 之前的 HiveMind
 
如此漂亮的术语,意味着什么呢?
 
分布配置是 Tapestry IoC 支持扩展的一个关键特性。
 
这个分布的部分事实上是引用任何可以贡献给任何服务的配置(服从通常的可见规则适用于私有服务)。
 
这似乎深奥,但非常容易上手,通过例子解释一下:
 
假定你正构建一个服务,比方说, map 映像一个扩展了 FileServicer 接口的文件。有很多不同的但都实现了 FileServicer 接口的服务,跨越多个不同的模块, 每个为一个特别类型的文件做特定的事。(通过扩充的文件确定)
 
 
一个核心服务使用这个配置来选择一个特定的 FileService 接口:
 
  1. public static FileServicer buildFileServicerDispatcher(Map<String,FileServicer> contributions)   
  2. {   
  3.    return new FileServiceDispatcherImpl(contributions);   
  4. }   
 
为了提供一个值给 contribution 参数, Tapestry 将从服务的贡献方法中收集贡献。它将确保 key value 匹配显示的泛型类型( String key 类型, FileServicer value 类型)。这个 map 将被装配然后传递给服务构建器方法,并且从那里,进入 FileServiceDispatcherImpl 构造器。
 
值来自哪里?服务贡献器方法,方法以 "contribute": 开头。
  1. public static void contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer> configuration)   
  2. {   
  3.    configuration.add("txt"new TextFileServicer());   
  4.    configuration.add("pdf"new PDFFileServicer());   
  5. }    
  6.   
像服务构建器和服务装饰器方法,我们可以注入我们想要得服务。
  1. public static void contributFileServicerDispatcher(MappedConfiguration<String,FileServicer> configuration,   
  2.   
  3.    @InjectService("TextFileServicer") FileServicer textFileServicer,   
  4.       
  5.    @InjectService("PDFFileServicer") FileServicer pdfFileServicer,   
  6. {   
  7.    configuration.add("txt", textFileServicer);   
  8.    configuration.add("pdf", pdfFileServicer);   
  9. }   
扩充性来自多个模块可能都导致相同的服务配置 :
  1.   public static void contributeFileServicerDispatcher(MappedConfiguration<String,FileServicer> configuration)   
  2. {   
  3.    configuration.add("doc"new WordFileServicer());   
  4.    configuration.add("ppt"new PowerPointFileServicer());   
  5. }   
.
现在 FileServicerDispatcher 构建器方法获得了一个 Map 通过它内部的至少四个途径。
 
因为 Tapestry IoC 是高度动态的(它浏览可见的 JAR manifest 文件来确定模块构建器类),这个 FileServicerDispatcher 服务可以在一个模块内,并且其他的贡献的模块(例如一个贡献 Office 文件服务)可以在更晚的时间被写。没有变化对于 FileServicerDispatcher 服务或它的模块构建器类,新的服务 "plug into" 全面的解决方案,只是通过拥有他们的 JAR 在运行时 classpath 上。
 
配置类型
 
有三个不同的配置样式(用来匹配贡献)。
1.          无序集合 Collection 。贡献被简单的添加并且顺序不重要。
2.          . 有序列表 list 。贡献作为一个有序列表被提供。贡献必须通过给每个贡献对象的唯一 id 确认顺序,通过在值之间的向前和向后依赖。
3.          Map 映像。贡献提供唯一的 key 和相对的 value
 
  •   无序集合( Collection
 
一个服务构建器方法可以通过定义一个 java.util.Collection 类型参数收集一个无序的值列表。此外,你应该标识聚集的参数类型。 Tapestry 将定义参数化的类型并且确保所有贡献匹配。
 
有一点要记住的是,贡献发生的顺序是未指定的。 可能有大量模块,每个模块有零个或更多个方法贡献给服务。这些方法被调用的顺序是未知的。
 
例如,这是一种需要一些 Runnable 对象的 Startup 服务。它不关心 Runnable 对象被执行的顺序。
 
  1. public static Runnable buildStartup(final Collection<Runnable> configuration)   
  2. {   
  3.    return new Runnable()   
  4.    {   
  5.      public void run()   
  6.      {   
  7.        for (Runnable contribution : configuration)   
  8.          contribution.run();   
  9.      }   
  10.    };   
  11. }   
 
这里,我们甚至不需要为这个实现而分割类,为这个实现我们使用一个内部类。重点是,配置被提供给构建器方法,传递它给服务实现。
 
在贡献方面,一个服务贡献方法看作是一个Configuration对象。
  1. public static void contributeStartup(Configuration<Runnable> configuration)   
  2. {   
  3.    configuration.add(new JMSStartup());   
  4.    configuration.add(new FileSystemStartup());   
  5. }       
这个Configuration接口只是定义了一个专一方法:add()。这是非常有意图的:你唯一可以做的就是添加新的项目。如果我们传递在一个Collection内,你可能被吸引去检查它的值,或者删除它们。。。但是运行在面前的事实是执行这些服务贡献方法的顺序是未知的。
 
对于可读性(如果Java仍继续支持这个概念),我们已经参数化了这个方法的配置参数,强制它为一个java.lang.Runnable实例,以致其匹配相应的参数。这是一个选择,但通常这非常有用。在任何时候,试图贡献一个没有扩展或实现Runnable类型的对象都将导致一个运行时警告(并且这个值将被忽略)。
 
Tapestry 只支持简单形式的参数化类型。Java泛型支持一个宽形式,“通配符”,是Tapestry不接受的。
  • 有序列表
 
有序列表更通用。使用一个有序的列表,这个贡献在被提供给服务构建器方法前被存储在一个正确的顺序内
 
此外,服务贡献方法被调用的顺序是未知的。因此,被加入给配置的对象的顺序是未知的。代替的是,我们强制项目的顺序毕竟所有贡献已经被添加。因为使用服务装饰器,我们通过每个贡献对象的唯一id设置顺序,然后通过id确定那个项目在列表前面,那个必须跟谁其后。
 
这样看来,如果我们的Startup服务需要一个明确的顺序用来启动:
  1. public static Runnable buildStartup(final List<Runnable> configuration)   
  2. {   
  3.    return new Runnable()   
  4.    {   
  5.      public void run()   
  6.      {   
  7.        for (Runnable contribution : configuration)   
  8.          contribution.run();   
  9.      }   
  10.    };   
  11. }   
 
注意这个服务构建器方法隔离了如何排序项目顺序的细节。它不用必须知道ids和之前还有之后的必需品。通过使用一个List类型参数,我们已经触发了Tapestry去收集所有排序信息。
 
对于我们的服务贡献方法,我们必须提供一个OrderedConfiguration类型参数:
  1.   
  2. public static void contributeStartup(OrderedConfiguration<Runnable> configuration)   
  3. {   
  4.    configuration.add("JMS"new JMSStartup());   
  5.    configuration.add("FileSystem"new FileSystemStartup(), "after:CacheSetup");   
  6. }     
 
通常你不用关心排序, add 方法的第一种形式因而被使用。排序规则将发现一个基于其他贡献对象约束的对象位置(这里是JMSStartup 实例)。
 
对于"FileSystem"贡献,一个约束已经被指定,指示FileSystem应该排在某些其他的名为"CacheSetup"的贡献之后。一些这样的排序约束可以被指定(add()方法接受可变数目的参数)。
 
传递的对象可以为null:这是有效的,并且视为一个"连接点":在列表内的相关的点对于他们自身没有任何意义,但当排序其他项目时可被使用。
 
Null值,一旦排序就被删除(List传递给服务构建器方法不包括任何null值)。此外,他们被允许作为站位符,为实际贡献的对象在他们自身周围组织。
 
映像的配置
 
象较早的例子中讨论的,映像的配置也被支持。传递的key必须唯一。当冲突发生时,Tapestry将记录警告(确定来源,根据调用的方法,冲突的),然后忽略冲突的值。
 
这个值不应为null。
 
对于key类型是字串的映像的配置, CaseInsensitiveMap 将会自动地被用 (并且传给服务构建器方法), 帮助确定忽略大小写是自动和普遍的。
 
注入的资源
 
除了注入服务在贡献器方法内(经由@InjectService 和 @Inject标注),Tapestry 将切断参数类型允许其他内容被注入。
²        ObjectLocator: 有权使用其他可见的服务给贡献模块。
这些情况不需要标注。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值