有人能清晰地解释一下为什么Google Guice很有用吗?

42

我已经阅读了关于Google Guice的文章,并了解了其他依赖注入方法存在的一般问题,但是我还没有看到有人在实践中使用Guice的例子,以便更加清楚地了解其价值所在。

我想知道是否有人知道这样的例子?

3个回答

46

使用Google Guice来提供单元测试的便利只是一个高级别的优点。有些人甚至在他们的项目中都不使用单元测试。人们一直在使用Spring/依赖注入,而不仅仅是用于单元测试。

使用Google Guice的低级别优势是关于应用程序内的内聚性问题,你的项目中的类之间可以松散耦合。我可以为另一个类提供一个类,而它们彼此之间并不依赖。

考虑以下示例:

public class A {

}

public class B {
  A a = new A();
}

B类将与A类紧密耦合,换句话说,它依赖于A类的存在。

但使用Guice,我可以这样使其松散耦合:

public class B {
    private A a;
    
    @Inject
    public B(A a) {
        this.a = a;
    }
}

现在,类BA松耦合,Guice负责提供A的实例而不是B必须去实例化它。通过这种方式,您可以将其扩展为提供A接口给B,如果您想对应用程序进行单元测试,则实现可以是模拟对象。

话虽如此,我们仅讨论了依赖注入的好处。除了依赖注入之外,使用Google Guice的好处包括:

  1. Guice具有非常清晰的构造函数注入实现。正如您从示例中看到的那样,只需在构造函数中添加@Inject注释即可。
  2. Guice还可以使用相同的注释进行Setter注入。
  3. 话虽如此,基于注释的注入比其他DI实现中的基于XML的注入更加清晰。
  4. 所有依赖注入和配置都使用Java,因此您默认情况下可以确保应用程序的类型安全性。
  5. Guice具有非常轻量级的面向方面编程实现(或者您可以将其称为AOPAlliance AOP实现的包装器)。好的一面是它不会生成存根或任何东西。

这是其中的概述。但是,随着您深入了解Guice,还有更多非常好的东西。一个简单的现实生活示例是,如果您正在使用MVP实现的GWT,则GWT应用程序中的组件/小部件之间耦合度非常低且不紧密集成在一起。


1
你首先说测试只是高层次的,而不是唯一的优势,然后你展示了现在 B 不再与 A 耦合,但似乎你提到的唯一优势是现在你可以为测试提供模拟对象。对我来说,B 仍然与 A 耦合,但它不再负责实际构造实例。 - Koray Tugay
我已经阅读了Guice几天了,我感觉人们只是想为了好玩而使用它。我曾经在大约8000万行代码的产品上工作过,但仍然没有必要在某些地方紧密耦合代码。第二个问题:代码紧密耦合有什么问题?对于测试部分,您可以使用PowerMockito等框架实际模拟任何内容。我们将项目划分为模块,并在模块类内部进行紧密耦合,在外部则由接口驱动。 - dvsakgec

19
也许你应该回到过去,更仔细地看待Guice想要解决的问题。为了理解Guice背后的动机,《TheServerSide.COM》上Bob Lee: I Don't Get Spring新闻(以及其评论)是完美的起点。然后,可以继续阅读Google Guice, A Java Dependency Injection Framework的公告(以及评论)和Tech Talk: Bob Lee on Google Guice(以及评论)。
就我个人而言,我对邪恶的XML表示担忧:XML配置地狱、XML可能引起的运行时错误、易于出错且不利于重构的字符串标识符等等。实际上,我认为对Spring和并发性持怀疑态度对每个人(包括Spring)都有好处。因此,我很高兴在DI框架领域看到一个新的参与者,特别是一个利用Java 5功能(泛型和注释,以确保类型安全)的现代框架。

因为谷歌在关键任务应用中运行Guice(几乎每个基于Java的应用程序也是Guice应用程序:AdWords、Google Docs、Gmail,甚至是YouTube,如“疯狂”的Bob Lee在Guice²中所报告的),我不相信Guice完全错误且没有提供任何价值。可悲的是,我认为谷歌不会提供这些应用程序的大量代码作为示例……但您可以在使用Guice的应用程序列表和/或第三方Guice插件列表中找到有趣的东西。或者查看Guice²中提到的书籍。或者问问Bob :)


“重构不利的字符串标识符”是什么意思?您能详细解释一下吗? - Geek

4

我认为编写接口、测试和代理是有优势的。

编写接口可以帮助保持代码分层,使得可以注入模拟对象进行测试,并且可以自动生成代理,这样客户端代码就不需要关心实现细节。

这对于Guice、Spring、PicoContainer以及所有DI框架都适用。

简明扼要吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接