简体   繁体   English

服务定位器与依赖注入

[英]Service Locator vs. Dependency Injection

I'm reviewing code with a lot of statements like this:我正在用很多这样的语句审查代码:

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

I would expect something like我希望像

private SomeInterface x;

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

Is there something wrong with the first approach?第一种方法有问题吗? Ok, dependencies are not so obvious, but implementations could easily be swapped through configuration of Locator.好的,依赖关系不是那么明显,但是可以通过 Locator 的配置轻松地交换实现。

Martin Fowler wrote an article on DI versus Locators : Martin Fowler 写了一篇关于 DI vs Locators的文章:

For DI:对于 DI:

  • Easier to determine what dependencies a component has - look at constructor.更容易确定组件具有哪些依赖项 - 查看构造函数。
  • Component does not have dependency on Service Locator so there is not a problem if the component is used with a different framework.组件不依赖于 Service Locator,因此如果该组件与不同的框架一起使用,则不会出现问题。
  • DI may make testing easier but a good Service Locator mechanism will make stubbing equally feasible DI 可能使测试更容易,但良好的服务定位器机制将使存根同样可行

Against DI:反对 DI:

  • Harder to debug and understand.更难调试和理解。
  • Component cannot request extra services from injector once it had been configured.组件一旦配置就不能从注入器请求额外的服务。

I personally don't think there's anything inherently bad with the first locator based approach - I guess DI does standardise this though, so if it's available I would use it.我个人认为第一个基于定位器的方法本质上没有什么不好的——我猜 DI 确实对此进行了标准化,所以如果它可用,我会使用它。 All good ideas tend to end up as frameworks at some point, so this has what's happened here.所有好的想法都倾向于在某个时候最终成为框架,所以这就是这里发生的事情。 Plus with DI you can take advantage of other annotations, scopes, etc. without having to roll your own code.再加上 DI,您可以利用其他注释、范围等,而无需编写自己的代码。 And the less bespoke code your project uses the better IMO.您的项目使用的定制代码越少,IMO 就越好。 I'll leave the last word to Fowler though:不过,我会把最后一句话留给福勒:

The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application.服务定位器和依赖注入之间的选择不如在应用程序中将服务配置与服务使用分离的原则重要。

First example: x = Locator.getInstance(SomeInterface.class) is looks like Service Locator pattern, and http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx check this article it says Service Locator is an anti-pattern and should be avoided第一个例子:x = Locator.getInstance(SomeInterface.class) 看起来像服务定位器模式,并且http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx检查这篇文章它说服务定位器是一个反-模式,应该避免

And for the second usage its all fine i like Constructor Injection, its smooth fine implementation.对于第二种用法,我喜欢构造函数注入,它的顺利执行非常好。 But I would like to not to use Attributes ( annotanitons in Java?) cause anytime i might want to change DI container i am using and i dont want to remove an attribute from all classes.但我不想使用属性(Java 中的注释?)因为任何时候我可能想要更改我正在使用的 DI 容器并且我不想从所有类中删除属性。

Service locator pattern uses a central registry known as the "service locator" which on request returns the information necessary to perform a certain task.服务定位器模式使用称为“服务定位器”的中央注册表,它根据请求返回执行特定任务所需的信息。

These are the worst sides of Service Locator Design Pattern:这些是服务定位器设计模式最糟糕的方面:

  • Things placed in the registry are effectively black boxes with regards to the rest of the system.对于系统的 rest,放置在注册表中的内容实际上是黑匣子。 This makes it harder to detect and recover from their errors, and may make the system as a whole less reliable.这使得检测和从错误中恢复变得更加困难,并且可能使整个系统的可靠性降低。

  • The registry must be unique, which can make it a bottleneck for注册表必须是唯一的,这可能使其成为
    concurrent applications.并发应用程序。

  • The registry can be a serious security vulnerability, because it allows outsiders to inject code right into an application.注册表可能是一个严重的安全漏洞,因为它允许外部人员将代码直接注入应用程序。

  • Can't pass dependencies by constructor (as we do in DI pattern) and hard to unit-test无法通过构造函数传递依赖项(就像我们在 DI 模式中所做的那样)并且难以进行单元测试

And I my opinion using service locator design pattern is acceptable only on top level of your application when your service locator probably will not change而且我认为只有在您的服务定位器可能不会改变时,才可以在应用程序的顶层使用服务定位器设计模式

There's nothing "wrong" as such with the service locator pattern,服务定位器模式并没有什么“错误”,

In this particular case, the one major argument in favor of DI would be testability.在这种特殊情况下,支持 DI 的一个主要论点是可测试性。

Without a doubt, DI allows for better unit testing.毫无疑问,DI 允许更好的单元测试。 The static getInstance method on Locator makes it more difficult to test in isolation. Locator 上的 static getInstance 方法使得单独测试变得更加困难。

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

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