嗨,今天,我想简单地讨论将依赖项注入您的类的不同方式。
通常,您有以下三种注射方法
- 直接进入字段/属性
- 通过显式的setter方法
- 通过显式的构造函数参数
现场注入
这种类型的注入为将所需的依赖项注入到类中提供了某种反射机制。
尽管这种注入类型的好处是,它消除了诸如setter方法或构造函数参数之类的混乱代码,但其缺点是这些依赖性是不可见的。 如果从外部查看类,则只会看到公共方法,并且可能是构造函数。
即使这使您非常清楚地了解了类提供的服务,但在我看来,它仍然具有以下主要缺点:
在为此特定类编写测试时,您必须检查该类以查看所需的依赖项,并且必须使用DI框架(即使是简单的测试),也必须使用一种反射机制来注入依赖项(模拟/存根/真实)。
更糟糕的是,传入依赖项的数量隐藏在该类中。 当然,您可以使用工具(JDepend等,pp。)告诉您依赖性的数量和方向,或者使用一个文件来指定注入,但是您必须依靠这种工具或检查类。
我观察到的另一个缺点是,与使用Setter或Constructor Injection的情况相比,创建具有多个职责的类的机会更高。
就像是:
哦,让我们使用这个精美的注解在这里注入我们需要的服务...几天/几小时后:测试这种野兽是如此的困难
二传手注射
注入器注入工具注入器方法,每个依赖项一个,DI框架用于注入依赖项。
这是一个变体,它使依赖项显式显示,并且使您可以清楚地了解特定类的依赖项。
在测试过程中,它的好处是您不必使用DI框架或反射机制,而可以直接设置依赖项。
这种方法的缺点是:您可以构造处于无法使用状态的类。 这是因为如果需要或可选依赖项,则无法与外部区分开。
构造函数注入
构造函数注入对类的构造函数进行检测,DI框架使用该类来注入依赖项。 这是使依赖关系明确的另一个变体。
与Setter注入相反,它可以防止您在不规则状态下创建类。 (当然,您可以传递null,但这不仅仅是一种作弊,对吗?)所以我要说,这是最严格的变体:
每个依赖项都是强制性的
这种注射类型的好处是
- 您必须只阅读一种方法,即构造函数,才能弄清楚此类的依赖关系。
- 您创建了一个不可变的类,它使缓存变得如此简单
同样,这里的缺点是您无法区分可选依赖项和必需依赖项。 构造函数强制设置所有字段。
我要讨论的最后一个变体是:
混合二传手和构造剂注射
我个人更喜欢此变体,混合了Setter和Constructor注入。
这给您:
- 在合同级别上区分强制性依赖项和可选性的能力
- 清楚说明特定类的依赖项是什么
- 使您可以轻松地检查班级是否负有重大责任
- 构建后正确配置的类
与纯方法类似,使用这种注入进行测试非常简单。 您不需要DI框架,并且可以轻松地将模拟的/存根的/真实的实现传递到要测试的类中。
使用/喜欢什么?
这个答案在很大程度上取决于您的框架/团队规则/语言。
但是我强烈建议您使用显式注入变量之一,因为它们使您无需使用依赖注入框架即可编写纯单元测试。
翻译自: https://www.javacodegeeks.com/2015/01/dependency-injection-field-vs-constructor-vs-method.html