本文翻译自:How to avoid Dependency Injection constructor madness?
I find that my constructors are starting to look like this: 我发现我的构造函数开始看起来像这样:
public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )
with ever increasing parameter list. 不断增加的参数列表。 Since "Container" is my dependency injection container, why can't I just do this: 由于“容器”是我的依赖项注入容器,所以为什么我不能这样做:
public MyClass(Container con)
for every class? 每堂课? What are the downsides? 不利之处是什么? If I do this, it feels like I'm using a glorified static. 如果执行此操作,则感觉就像我在使用精美的静态方法。 Please share your thoughts on IoC and Dependency Injection madness. 请分享您对IoC和依赖注入疯狂的想法。
#1楼
参考:https://stackoom.com/question/a9Bn/如何避免依赖注入构造函数的疯狂
#2楼
You are right that if you use the container as a Service Locator, it's more or less a glorified static factory. 没错,如果您将容器用作服务定位器,则它或多或少是光荣的静态工厂。 For lots of reasons I consider this an anti-pattern . 由于种种原因, 我认为这是一种反模式 。
One of the wonderful benefits of Constructor Injection is that it makes violations of the Single Responsibility Principle glaringly obvious. 构造函数注入的奇妙好处之一是,它使违反单一责任原则的行为显而易见。
When that happens, it's time to refactor to Facade Services . 发生这种情况时,就该重构为Facade Services了 。 In short, create a new, more coarse-grained interface that hides the interaction between some or all of the fine-grained dependencies you currently require. 简而言之,创建一个新的,更粗粒度的接口,以隐藏您当前需要的一些或所有细粒度依赖项之间的交互。
#3楼
I don't think your class constructors should have a reference to your IOC container period. 我认为您的类构造函数不应引用您的IOC容器时间。 This represents an unnecessary dependency between your class and the container (the type of dependency IOC is trying to avoid!). 这表示您的类与容器之间不必要的依赖关系(IOC试图避免的依赖关系类型!)。
#4楼
The difficulty of passing in the parameters is not the problem. 传递参数的困难不是问题。 The problem is that your class is doing too much, and should be broken down more. 问题是您的课程做得太多,应该细分得更多。
Dependency Injection can act as an early warning for classes getting too big, specifically because of the increasing pain of passing in all of the dependencies. 依赖注入可以作为类过大的预警,特别是因为传递所有依赖的痛苦越来越大。
#5楼
What dependency injection framework are you using? 您使用什么依赖注入框架? Have you tried using setter based injection instead? 您是否尝试过使用基于setter的注入?
The benefit for constructor based injection is that it looks natural for Java programmers who don't use DI frameworks. 基于构造函数的注入的好处是,对于不使用DI框架的Java程序员来说,它看起来很自然。 You need 5 things to initialize a class then you have 5 arguments for your constructor. 您需要5件事来初始化一个类,然后为构造函数提供5个参数。 The downside is what you have noticed, it gets unwieldy when you have lots of dependencies. 缺点是您已经注意到,当您有很多依赖项时,它变得笨拙。
With Spring you could pass the required values with setters instead and you could use @required annotations to enforce that they are injected. 使用Spring时,您可以通过setter传递所需的值,并且可以使用@required注释强制注入它们。 The downside is that you need to move the initialization code from the constructor to another method and have Spring call that after all the dependencies are injected by marking it with @PostConstruct. 缺点是您需要将初始化代码从构造函数移至另一个方法,并在将所有依赖项注入后通过@PostConstruct标记为Spring进行调用。 I'm not sure about other frameworks but I assume they do something similar. 我不确定其他框架,但我认为它们会做类似的事情。
Both ways work, its a matter of preference. 两种方法都起作用,这是一个优先事项。
#6楼
I came across a similar question about constructor based dependency Injection and how complex it was getting to pass in all the dependencies. 我遇到了一个类似的问题,关于基于构造函数的依赖注入,以及如何传递所有依赖的复杂性。
One of the approach, I have used in past is to use the application facade pattern using a service layer. 我过去使用的一种方法是通过服务层使用应用程序外观模式。 This would have a coarse API. 这将具有粗略的API。 If this service depends on repositories, It would use a setter injection of the private properties. 如果此服务依赖于存储库,它将使用setter注入私有属性。 This requires creating an abstract factory and moving the logic of creating the repositories into a factory. 这需要创建一个抽象工厂,并将创建存储库的逻辑转移到工厂中。
Detailed code with explanation can be found here 带有说明的详细代码可以在这里找到
Best practices for IoC in complex service layer 复杂服务层中IoC的最佳做法