【问题标题】:Google Guice vs. PicoContainer for Dependency InjectionGoogle Guice 与 PicoContainer 的依赖注入
【发布时间】:2023-12-20 09:38:01
【问题描述】:

我的团队正在研究依赖注入框架,并试图在使用 Google-Guice 和 PicoContainer 之间做出决定。

我们正在我们的框架中寻找几样东西:

  1. 代码占用量小 - 我所说的代码占用量小是指我们不希望代码库中到处都是依赖注入代码。如果我们需要在未来进行重构,我们希望它尽可能简单。
  2. 性能 - 每个框架在创建和注入对象时有多少开销?
  3. 易于使用 - 是否有很大的学习曲线?我们是否必须编写大量代码才能使一些简单的工作正常工作?我们希望配置尽可能少。
  4. 社区规模 - 较大的社区通常意味着将继续维护项目。我们不想使用框架并且必须修复我们自己的错误;)此外,我们在此过程中遇到的任何问题都可以(希望)由框架的开发人员/用户社区回答。

非常感谢根据所列标准对这两个框架进行比较。任何有助于比较两者的个人经历也会非常有帮助。

免责声明:我对依赖注入还很陌生,所以如果我问了一个与本次讨论无关的问题,请原谅我的菜鸟。

【问题讨论】:

标签: java dependency-injection guice picocontainer


【解决方案1】:

您可能希望将 Spring 包含在您正在考虑的依赖注入框架列表中。以下是您的问题的一些答案:

与框架耦合

Pico - Pico 倾向于阻止 setter 注入,但除此之外,您的类不需要了解 Pico。只需要知道接线(所有 DI 框架都是如此)。

Guice - Guice 现在支持标准的JSR 330 注释,因此您的代码中不再需要特定于 Guice 的注释。 Spring 也支持这些标准注解。 Guice 人使用的论点是,如果没有运行 Guice 注释处理器,如果您决定使用不同的框架,这些应该不会产生影响。

Spring - Spring 旨在让您避免在代码中提及 Spring 框架。因为他们确实有很多其他帮助程序/实用程序等。不过,依赖 Spring 代码的诱惑非常强烈。

性能

Pico - 我对Pico的速度特性不是太熟悉

Guice - Guice 的设计速度很快,参考文献中提到的比较有一些数字。当然,如果速度是首要考虑因素,则应考虑使用 Guice 或手动接线

春天 - 春天可能很慢。已经有工作让它更快,使用 JavaConfig 库应该会加快速度。

易于使用

Pico - 易于配置。 Pico 可以为您做出一些自动接线决定。不清楚它如何扩展到非常大的项目。

Guice - 配置简单,您只需添加注释并从 AbstractModule 继承即可将事物绑定在一起。由于将配置保持在最低限度,因此可以很好地扩展到大型项目。

Spring - 相对容易配置,但大多数示例使用 Spring XML 作为配置方法。随着时间的推移,Spring XML 文件会变得非常庞大和复杂,并且需要时间来加载。考虑使用 Spring 和手动依赖注入的组合来克服这个问题。

社区规模

Pico - 小

Guice - 中等

弹簧 - 大

经验

Pico - 我没有太多使用 Pico 的经验,但它不是一个广泛使用的框架,因此更难找到资源。

Guice - Guice 是一个流行的框架,当您有一个大型项目需要重新开始大量开发时,它对速度的关注是受欢迎的。我担心配置的分布式特性,即不容易看到我们的整个应用程序是如何组合在一起的。这方面有点像AOP。

Spring - Spring 通常是我的默认选择。也就是说,XML 可能会变得很麻烦,并且由此导致的速度变慢很烦人。我经常最终使用手工制作的依赖注入和 Spring 的组合。当你真正需要基于 XML 的配置时,Spring XML 是相当不错的。 Spring 还付出了很多努力来使其他框架对依赖注入更加友好,这很有用,因为它们在这样做时经常使用最佳实践(JMS、ORM、OXM、MVC 等)。

参考文献

【讨论】:

  • 我学到的(从其他人而不是从自己使用它)是 PicoContainer 比 Guice 更轻量级。此外,通过 PicoContainer 文档查看它似乎也更易于使用。它将在构造函数本身中搜索依赖项,您无需指定要使用的构造函数。它只是使用一个匹配的。
  • 是的,我现在很喜欢 PicoContainer。它只是一个“保持简单”但有效的解决方案,我不禁认为 Spring 现在臃肿和过时。 Guice 也不错(并且拥有 Google 的良好支持者),但我相信 Pico 也有更多的功能/灵活性,因为它比较老。很高兴看到讨厌的 xml 配置的替代方案!
  • 只是我的看法:我从 Pico 切换到 Guice 是因为我觉得 Guice 更易于使用。向组件添加注释会增加依赖关系,但这对我们来说并不是一个重要因素,因为 Guice 基本上是两个 jar。从好的方面来说,在构造函数上使用 @Inject 可以让其他开发人员意识到该对象是一个组件。也就是说,我认为 Pico 没有任何错误。我只是发现 Guice 更易于使用。
  • 我在许多非常大(且使用量很大)的​​项目(每个容器中定义了数百个组件类型)中使用 pico,并使用了它的所有各种功能,并且非常高兴用它。
  • 我刚刚用 Guice/Spring/PicoContainer 做了一个简单的性能测试——Guice 和 PicoContainer 非常相似。在某些情况下,Guice 会快一些。在所有情况下,春天都非常缓慢。
【解决方案2】:

jamie.mccrindle 提出的答案实际上非常好,但我很困惑为什么 Spring 是默认选择,因为很明显可以使用更好的替代品(Pico 和 Guice)。 IMO Spring 的受欢迎程度已经达到了顶峰,现在它正在靠炒作(以及所有其他“我也是”Spring 子项目希望赶上 Spring 潮流)。

Spring 唯一真正的优势是社区规模(坦率地说,由于规模和复杂性,它是必需的),但 Pico 和 Guice 并不需要庞大的社区,因为他们的解决方案更简洁,更有条理,更优雅。 Pico 似乎比 Guice 更灵活(您可以在 Pico 中使用注释,也可以不使用 - 它非常有效)。 (编辑:意思是说它非常灵活,并不是说它效率不高。)

Pico 的小尺寸和缺乏依赖性是一个不容小觑的重大胜利。您现在需要下载多少兆才能使用 Spring?这是一个由大量 jar 文件组成的杂乱无章的文件,其中包含所有依赖项。直观地思考,这样一个高效且“小”的解决方案应该比 Spring 之类的解决方案具有更好的扩展性和性能。 Spring 的膨胀真的会使其扩展性更好吗?这是奇异的世界吗?在证明(和解释)之前,我不会假设 Spring “更具可扩展性”。

有时创造一些好的东西(Pico/Guice)然后让你的手离开它而不是添加膨胀和厨房水槽功能以及无穷无尽的新版本确实有效......

【讨论】:

  • 想说为什么 Pico 和 Guice 优于 Spring?
  • 我以为我做到了——基本上,他们也做 DI,他们更简单/更小/更干净,没有或很少依赖。这并不是说 Spring 从不 有意义(我确信有案例),我只是说,如果满足您的要求,越简单越好。对于大量项目,您只需要小型支持库。
【解决方案3】:

注意:这更像是评论/咆哮而不是答案

PicoContainer 很棒。如果他们只是修复他们的网站,我会切​​换回它。现在真的很困惑:

我现在使用的是 Guice 2.x,尽管它更大,而且功能更少。查找文档要容易得多,而且它的用户组非常活跃。但是,如果 Guice 3 的方向有任何迹象,那么 Guice 似乎开始膨胀,就像 Spring 在早期所做的那样。

更新:我向 Pico Container 人员发表了评论,他们对网站进行了一些改进。现在好多了!

【讨论】:

  • 但 codehaus 网站仍然冻结,没有任何移动的信息。我以为 Pico 已经死了;)
  • 如果网站的代码不是最新的,则可能表明该项目已低于临界质量。
  • @ThorbjørnRavnAndersen 是的。不幸的是,我认为 Pico 已被 Guice 和 CDI 取代。
  • 截至 2013 年 3 月 8 日,picocontainer.org 网站似乎被域名抢注者占据。 picocontainer.com 现在似乎是规范网站。
【解决方案4】:

这是一个老问题,但今天你可以在你的 Android 应用项目中考虑 Dagger (https://github.com/square/dagger)。 Dagger 在编译时生成代码。因此,您可以获得更短的启动时间和更少的执行时间内存使用量。

【讨论】:

  • 我喜欢 Dagger,但似乎公共存储库中还没有用于非 Android 项目的 Gradle 插件(即用于“常规”Java 项目的 Gradle 插件)。如果公共存储库中有插件,我会考虑将它用于 Java 项目。
【解决方案5】:

如果您想要一个简约的 DI 容器,您可以查看Feather。 Vanilla JSR-330 仅 DI 功能,但在占用空间(16K,无依赖性)和性能方面相当不错。适用于安卓。

【讨论】:

  • 嘿,羽毛真棒!我用它为ActFramework 实现了DI plugin。我做了一些更新,例如如果需要,自动调用 injectFields,并支持注入监听器,如果你想让我发回拉取请求,请告诉我
  • @green 我看到你已经搬到 Genie。能否请您分享您使用 Feather 的经验?
  • @beerBear Feather 在大多数 DI 用例中非常轻巧且易于使用。但是,由于我正在研究全栈 MVC 框架,因此我需要一个实现完整 JSR330 规范的解决方案。这就是我搬到 Genie 的原因
  • @green 感谢您的解释,以便更好地理解。
【解决方案6】:

虽然我确实喜欢 PicoContainer,因为它很简单并且没有依赖关系。我建议改用 CDI,因为它是 Java EE 标准的一部分,因此您没有供应商锁定。

在侵入性方面,它的主要问题是容器的要求和使用相对空的 META-INF/beans.xml 文件(需要表明 jar 正在使用 CDI)和注释的使用(尽管它们是标准的)

我在自己的项目中使用的轻量级 CDI 容器是 Apache Open Web Beans。虽然花了一段时间才弄清楚如何创建一个看起来像这样的简单应用程序(与 Pico 不同)。

public static void main(final String[] args) {
    final ContainerLifecycle lifecycle = WebBeansContext.currentInstance()
            .getService(ContainerLifecycle.class);
    lifecycle.startApplication(null);

    final BeanManager beanManager = lifecycle.getBeanManager();
    // replace Tester with your start up class
    final Bean<?> bean = beanManager.getBeans(Tester.class).iterator()
            .next();

    final Tester b = (Tester) lifecycle.getBeanManager().getReference(bean,
            Tester.class, beanManager.createCreationalContext(bean));
    b.doInit();
}

【讨论】:

  • 如果您在库代码中坚持使用 JSR-330,则可以将容器特定代码保持在最低限度。
  • 您在自动化测试中仍然需要特定于容器的代码。虽然这并不意味着您的实际代码中会包含特定于容器的代码(除非您打算运行自己的“main”,否则我不应该在我为自己编写的一个应用程序中运行它。