Google Guice 与 JSR-299 CDI / Weld
Posted
技术标签:
【中文标题】Google Guice 与 JSR-299 CDI / Weld【英文标题】:Google Guice vs. JSR-299 CDI / Weld 【发布时间】:2011-02-08 18:37:30 【问题描述】:Weld,JSR-299 上下文和依赖注入参考实现,认为自己是 Spring 和 Guice 的一种继承者。
CDI 受到许多现有 Java 框架的影响,包括 Seam、Guice 和 Spring。然而,CDI 有它自己非常独特的特点:比 Seam 更类型安全,比 Spring 更有状态且更少以 XML 为中心,比 Guice 更支持 Web 和企业应用程序。但是,如果没有上述框架的启发以及 JSR-299 专家组 (EG) 的大量协作和辛勤工作,就不可能有这些。
http://docs.jboss.org/weld/reference/latest/en-US/html/1.html
与 Guice 相比,是什么让 Weld 更适合企业应用?与Guice相比有什么优点或缺点吗?与 Weld 拦截器相比,您如何看待 Guice AOP?性能怎么样?
我的选择
最后我决定使用 Guice,因为我喜欢干净的编程模型,它默认除了 @Inject 之外几乎没有注释。在 Guice 中使用外部库比使用 CDI 容易得多。使用 Guice,AOP 也非常简单。
【问题讨论】:
仅供参考,截至 2017 年 4 月,CDI 2 已退出。请参阅:JSR 365: Contexts and Dependency Injection for JavaTM 2.0。 Weld 3 是参考实现。 【参考方案1】:CDI(焊接)尚未广泛使用,因此很难进行比较。几点:
CDI 的设计考虑了与 EJB3、JSF 和其他 JavaEE 标准的集成。 CDI 具有所谓的可移植扩展,允许第三方库与 CDI 实现的生命周期和内部功能集成 CDI 的设计考虑了所有可能的极端情况,因此它很可能涵盖了您需要的所有内容。 Spring、Guice 和 Seam 演变成这样的状态,而 CDI 则借鉴了这三者的经验。 在我看来,CDI 拦截器将无法满足 Spring AOP 已经满足的所有需求。 Guice AOP 可能也是如此。您不能使用 AspectJ 语法定义拦截器。 缺少 xml 定义既是优点也是缺点,有些人(在某些情况下是正确的)更喜欢 xml 配置。 如果不小心使用,限定符注释的扩展使用(在我看来)会产生一些大混乱。【讨论】:
关于第一个项目符号... CDI 2.0 现在还针对 Java SE(标准版)和 Java EE(企业版)的使用。见JSR 365。该规范现在分为几个部分:Part I: Core CDI、Part II - CDI in Java SE 和 Part III - CDI in Java EE。【参考方案2】:在尝试回答您的问题之前,让我先添加一条重要信息:JSR 330 (@Inject
) 已由 Guice 和 Spring 项目 (announcement from May 2009) 标准化,并且正在成为 reused in JSR 299。这涵盖了声明注入点方面的基本 DI 机制。
现在,回到这个问题 - 我在 Spring 方面的经验比在 Guice 方面的经验要多得多。
Weld 中的企业功能
Alternative configuration mechanisms 在 JSR-299 中有一个非常简洁的设计,并允许在 Java 代码之外进行配置机制 (beans.xml
)。
Events 是一个非常强大的东西,非常适合 JMS。我刚刚找到了一个Event Bus for Guice,但我不能说它是如何比较的。
Portable extensions 是一个 SPI,可用于与现有技术集成或以简洁的方式封装遗留代码。
优点/缺点
注意:我稍后会尝试在这里添加一些项目,但是这个答案已经比我预期的要长,对不起。
焊接/CDI
标准化:如果某样东西是标准化的并且有很好的实现,就会有很多人使用它。示例:Weld 中的 Built-in scopes 比 Guice 或 Spring 提供更多的范围。所有这些都可以扩展,但如果应用程序框架被大型社区使用,它们将更依赖于标准范围。 容器支持:这与前一项类似,但它是采用的主要论据。 Glassfish 和 JBoss 6 等主要开源应用服务器提供 CDI 支持(请参阅 here)。Guice/Spring
实际应用:大多数现有应用程序已经在使用 Guice/Spring。 Spring/Guice 始终建立在标准之上,并在不存在或无法使用标准的情况下提供新功能。如果您遵循各自的最佳实践,该框架将帮助您使您的应用程序基于标准且干净。AOP 和拦截器
这是一个被广泛讨论的话题,我不能偏袒一个。这两种机制都非常强大,但至少需要对应用程序的体系结构有最低限度的了解。还可以查看Decorators 和之前引用的Events。最好使用正确的工具,但不要忘记,如果开发人员必须使用其中一种机制,那么他/她理解这个概念是一件好事。
性能
很遗憾,我还不能对此进行研究,但我尝试遵循一些规则,尤其是在使用一个为您提供许多功能而您却没有注意到它的框架时:
尽可能在运行时使用单个接线步骤而不是多次查找。 如果可能,请在应用程序初始化时完成所有接线。 任何拦截步骤或 AOP 代理都会向堆栈添加一些方法调用。【讨论】:
我发现 Guice 中的编程配置比 beans.xml 更清晰(你又回到了“类名是配置文件中的字符串,而不是代码”的问题)。【参考方案3】:另一个区别是 CDI 非常面向 Java EE。它提供了一种将不同的 Java EE 子系统粘合在一起的机制。
即。通过使用 @Named("book")
注释 bean,该 bean 在统一的 EL(表达式语言)中被称为“book
”。
然后你可以在 JSF 页面中使用它,例如:
<h:outputLabel value="Book title:" for="bookTitle"/>
<h:outputText id="bookTile" value="#book.title"/>
【讨论】:
CDI 与 JavaEE 一起工作,但它可以在 JavaSE 环境中完美地使用,作为一个常规的 DI 框架。 @Bozho 是的,但是它还不支持“非托管实例”,这可能会导致一些 JavaSE 应用程序从 Pico/Guice/Spring 到 CDI 的艰难过渡. @Named 不是 JSR299 而是 JSR330 ...现在 Spring 也支持它。另一方面,我一直很好地在 SE 环境中使用 Weld。【参考方案4】:CDI 反对 Guice 的最重要特性是它是 Java EE 6 的标准部分。
这一点的重要性不容小觑,因为这意味着 CDI 是您在编写 Web 应用程序时应该使用的 DI 标准。
不久前,我研究了能够确定我们如何拥有标准核心发行版的技术 - 适当准备 - 我们可以随意添加额外的模块,这些模块可以覆盖现有功能而无需更改核心模块. IE。添加一个额外的 jar,该功能会自动激活。
事实证明,对我们在桌面和 Web 应用程序中使用的代码库执行此操作的最佳方法是对我们的代码使用 JSR-330 注释,然后使用 CDI 或 Guice(SVN,实现很快现在在 3.0) 作为引擎。
经过几个项目后,我发现我最喜欢 Guice 配置,而不是 Weld 中发生的不透明魔法。此外,我发现使用 Weld 执行上述我们想要的方法,我必须将额外 jar 中的类标记为 @Alternative,然后在 beans.xml 中提到我希望强制执行替代类(这不是对重构具有鲁棒性)。
但是,总而言之,JSR-330 允许我们做一些以前非常乏味和脆弱的事情(因为 new
绑定得非常紧密),这是一个巨大的胜利。如果您有这样的需求,我强烈建议您研究 DI。
【讨论】:
请注意,在重新访问后,我使用了@Provides
。效果比@Alternative
好得多。
由于 guice 在我们的目标平台上运行缓慢,我转向了 dagger,这太棒了!【参考方案5】:
CDI for Guice users 是一个很好的比较。
【讨论】:
【参考方案6】:我在 AWS Lambda 无服务器应用程序中使用了 Guice。 AWS 建议在 Lambda 函数中使用 Guice 或 Dagger 而不是 Spring。见AWS Lambda best practices
主要原因是 Guice 和 Dagger 是更小的框架,启动时间更快,这在 Lambda 中是必不可少的。
虽然 OP 没有提到 Spring,但 Spring 和 CDI/weld 都适用于企业级应用程序,这通常需要这些框架提供的附加功能。因此,对于只需要 DI 的小型应用程序,Guice 或 Dagger 将是最佳选择。
【讨论】:
以上是关于Google Guice 与 JSR-299 CDI / Weld的主要内容,如果未能解决你的问题,请参考以下文章
Apache Druid源码导读--Google guice DI框架
Apache Druid源码导读--Google guice DI框架