前不久 Red Hat 的 JBoss 部门发布了 Weld1.0.0——Java EE 6 对 JSR-299( Java EE 的上下文与依赖注入,即 Contexts and Dependency Injection for Java EE,后文简称为 CDI)的参考实现。Sun GlassFish Application Server v3 和即将发布的 JBoss AS 5.2.0 都使用了 Weld 实现,然而 Weld 并不需要完整的应用服务器。它可以运行在 Servlet 容器内如 Jetty 6.1 或是 Tomcat 6,同时也能用于 Java SE 5.0+。为了阐明后一点, Weld 发布包中还带有一个示例性的控制台应用及一个 Swing 应用示例。
在 JSR-299 草案首次发布后,Google 与 SpringSource 又联合提交了 JSR-330,旨在标准化“一个久经考验、无可辩驳的注解集以使得注入类能够跨越多个框架”,因此在我碰到 CDI 规范的领导者 Gavin King 时就迫不及待地询问他 JSR-330 对 CDI 有何影响。
CDI 现在使用 JSR-330 所定义的注解来声明注入点。这种影响是微乎其微的,因为 330 所使用的模型基本上与 299 大同小异。归结起来,只是注解名有所区别罢了。 要知道 330 并没有定义完整的依赖注入方案。它只定义了带有修饰符的注入点而已,其他的都没有定义。
InfoQ:CDI 和 EJB 是如何处理 EE 6 所引入的 Managed Bean 模型的?
新的 Managed Bean 规范是 JSR-299 的工作成果(在规范的早期草案中我们称之为“简单 Web Bean”)。简单 Web Bean 支持依赖注入、EL 名字与拦截器,但却没有 EJB 那些编程约束。 Managed Bean 规范引起了很多争议,Red Hat 说我们确实需要支持普通 Java 类的注入,而其他 EE 涉众则表示对 299 定义这样一个新 EE“组件”的行径感到非常不爽。
经过多次讨论后,我们认为这种“简单”组件的想法应该自成一个规范,以此构成所有其他 EE 组件编程模型的基础,包括 EJB 等等。这是一个非常棒的愿景,我们都很赞同这个观点,但 EE 6 并没有完全实现它。
最后的结果是:CDI 可以用在普通的 Java 类(现在叫做“Managed Bean”)以及 EJB 上。现在的 EJB 可以看作是一种特殊的 Managed Bean,只不过有一些额外的编程约束和功能。这种编程模型能够极大地降低新用户学习 EE 的曲线。
InfoQ:EJB 还需要自己的组件模型么?
我认为 EE 平台的未来发展方向是逐渐将 EJB 特有的功能通用化,将其应用在所有的 Managed Bean 上。举个例子,为何不是所有的 Managed Bean 都支持 @TransactionAttribute 和 @RolesAllowed 呢?简直没有道理嘛。 然而 EJB 在为消息传输定义端点、远程与异步方法调用、定时器等领域还是有一席之地的。在这些情况下,EJB 生命周期模型还是非常有意义的。
InfoQ:Seam 为 JSF 2 和 CDI 创造了灵感。在 JSF 中修复这些问题要比在 Seam 中解决好在哪呢?
在尽力透明化用户体验的过程中,我们从来都没有真正满意过。用户总是注意到何时在使用 JSF 的特性,何时在使用本应放在 JSF 中的 Seam 特性。
CDI 来源于 Red Hat 的开源 Seam 框架,从广义上来讲,它将 Seam 的编程模型标准化为 Java EE 6 的编程模型。CDI 实现了 Java EE 6 的 3 个主要目的。首先,它提供了声明的方式来管理绑定到上下文组件的范围、状态与生命周期。其次,它为平台提供了标准化、注解驱动、类型安全的依赖注入框架,方式类似于 Google Guice。最后,它为 Java EE 平台的扩展开发提供了 Service Provider Interface(SPI)。
CDI 的 Service Provider Interface 已经成为 Java EE 可扩展性的一个关键组成部分,而可扩展性则是 Java EE 6 的一个中心议题。 JSR-316 规范说到:
…我们相信大家都很渴望将这些技术用于 Java EE 应用服务器之上,或是以插件的形式使用。通过增加更多的扩展点和服务供应商接口,其他技术就可以插件的形式用于平台实现了,这么做既整洁又高效,对于开发者来说使用起来也是非常简单的,就像是内置于平台上的设备一样。
这一点大家可以从下一版的 Seam(也就是 Seam 3)中看到,Seam 3 将 CDI 作为其核心引擎并使用 CDI Service Provider Interface 提供了 CDI 中并没有涵盖的众多特性,如 BPM 集成、Drools 集成、PDF 与 Email 模板支持以及 Excel 生成等等。这些扩展(也包括第三方厂商提供的其他扩展)可以运行在支持 JSR-299 的任何环境中,也包括任何 Java EE 6 环境。CDI 规范说到:
可移植的扩展可以通过如下方式与容器集成: • 提供自己的 Bean、拦截器和装饰器。
• 通过依赖注入服务将依赖注入到自己的对象中。
• 为客户化的范围(custom scope)提供一个上下文实现。
• 通过外部注解增强或是提供基于注解的元数据。
Gavin King 说到:
CDI 和 JSF 2 的出现预示了 Seam 的新方向。 在 Seam 2 中,我们花费了巨大的精力填补 JSF 的漏洞,结果造成了没有时间集成那些非常吸引我们的表示层技术。JSF 2 可以让我们将精力放在其他领域中。
最重要的是,CDI 现在提供了一个核心“引擎”,可以在所有的 EE 6 应用服务器之间移植,甚至还可以用在 Tomcat、Jetty 和 Resin 上。该核心并不依赖于任何特定的表示层技术。其所拥有的仅仅是为可移植扩展开发者所提供的一套定义良好的 SPI。该 SPI 作为整个生态系统的根基。如果你是一位框架开发者,那现在就会明确要想将框架与 CDI 及 EE 环境集成起来(通过扩展)需要做哪些事情。这也许是 CDI 最令人激动的特性了。
Seam 3 将成为一套 CDI 可移植扩展,可以用在任何应用服务器上并向 CDI 编程模型提供扩展,同时能与我们感兴趣的其他技术进行集成。
JBoss CTO Mark Little说 CDI 和 Seam 将是其所有项目和平台的未来发展方向:
目前团队正与这些项目和平台(如 ESB 和 SOA-P)紧密合作以确保新版 Seam 能考虑到其特定的需求。重要的是,一些项目已经认为 Seam 是其正确的选择,甚至都不用做任何修改,因此紧密与快速的集成要比想象的更容易一些。
King 也确认了这一点并说到:
Red Hat 已经成功将 Seam 应用到其所开发的一些项目当中了。CDI 将 Seam 的核心功能放在了坚固的根基之上,而我们对 CDI 的实现 Weld 是个更加专注且测试良好的基础设施。这意味着我们可以将 Weld 应用在 Seam 2 不适合的各种领域中,而这与构建 Web 站点无关。
除了 Red Hat 外还有很多其他的 CDI 实现也即将破茧成蝶。Resin 的创建者 Caucho Technology 拥有一个实现( CanDI ),而 Resin 容器本身也在内部大量使用了 CDI。Apache 也正致力于一个名为 OpenWebBeans 的实现,Granite DS 也有一个实现,可以将 CDI 应用在 Flex 应用中,如下:
我们认为 JCDI 非常适合于事件驱动架构的 Flex RIA。JCDI 应用非常整洁,尽管 JBoss Seam 提供了大量的特性,但他们没必要再开发一个 RIA 前端了。
查看英文原文: Q&A with Gavin King on the Impact of JSR-299 and Weld 1.0 on Java EE and JBoss
评论