繁体   English   中英

服务定位器与依赖注入

[英]Service Locator vs. Dependency Injection

我正在用很多这样的语句审查代码:

private SomeInterface x = Locator.getInstance(SomeInterface.class)

我希望像

private SomeInterface x;

@Inject
public Consumer(SomeInterface x){ // constructor
    this.x = x;
}

第一种方法有问题吗? 好的,依赖关系不是那么明显,但是可以通过 Locator 的配置轻松地交换实现。

Martin Fowler 写了一篇关于 DI vs Locators的文章:

对于 DI:

  • 更容易确定组件具有哪些依赖项 - 查看构造函数。
  • 组件不依赖于 Service Locator,因此如果该组件与不同的框架一起使用,则不会出现问题。
  • DI 可能使测试更容易,但良好的服务定位器机制将使存根同样可行

反对 DI:

  • 更难调试和理解。
  • 组件一旦配置就不能从注入器请求额外的服务。

我个人认为第一个基于定位器的方法本质上没有什么不好的——我猜 DI 确实对此进行了标准化,所以如果它可用,我会使用它。 所有好的想法都倾向于在某个时候最终成为框架,所以这就是这里发生的事情。 再加上 DI,您可以利用其他注释、范围等,而无需编写自己的代码。 您的项目使用的定制代码越少,IMO 就越好。 不过,我会把最后一句话留给福勒:

服务定位器和依赖注入之间的选择不如在应用程序中将服务配置与服务使用分离的原则重要。

第一个例子:x = Locator.getInstance(SomeInterface.class) 看起来像服务定位器模式,并且http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx检查这篇文章它说服务定位器是一个反-模式,应该避免

对于第二种用法,我喜欢构造函数注入,它的顺利执行非常好。 但我不想使用属性(Java 中的注释?)因为任何时候我可能想要更改我正在使用的 DI 容器并且我不想从所有类中删除属性。

服务定位器模式使用称为“服务定位器”的中央注册表,它根据请求返回执行特定任务所需的信息。

这些是服务定位器设计模式最糟糕的方面:

  • 对于系统的 rest,放置在注册表中的内容实际上是黑匣子。 这使得检测和从错误中恢复变得更加困难,并且可能使整个系统的可靠性降低。

  • 注册表必须是唯一的,这可能使其成为
    并发应用程序。

  • 注册表可能是一个严重的安全漏洞,因为它允许外部人员将代码直接注入应用程序。

  • 无法通过构造函数传递依赖项(就像我们在 DI 模式中所做的那样)并且难以进行单元测试

而且我认为只有在您的服务定位器可能不会改变时,才可以在应用程序的顶层使用服务定位器设计模式

服务定位器模式并没有什么“错误”,

在这种特殊情况下,支持 DI 的一个主要论点是可测试性。

毫无疑问,DI 允许更好的单元测试。 Locator 上的 static getInstance 方法使得单独测试变得更加困难。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM