问题描述
我有点懒惰,习惯几乎完全用场注射。我只是提供空构造函数,把我的@Inject字段我看起来很好很简单。然而,现场注入有其权衡,所以我设计了一些简单的规则,帮助我决定何时使用字段以及何时使用构造函数注入。如果我的逻辑中存在错误或者您需要添加其他注意事项,我将不胜感激。
I was kind of lazy and used to use almost entirely field injections. I was just providing empty constructor, put my @Inject fields I everything was looking nice and simple. However field injection have its trade-offs so I've devised some simple rules that help me to decide when to used field and when to use constructor injections. I will appreciate any feedback if there is mistake in my logic or if you have additional considerations to add.
首先澄清以便在同一页面上:
First some clarification in order to be on the same page:
构造函数注入:
@Inject
public SomeClass(@Named("app version") String appVersion,
AppPrefs appPrefs) {...
与字段注入相同:
public class SomeClass {
@Inject
@Named("app version") String mAppVersion;
@Inject
AppPrefs appPrefs;
规则1:如果我不控制对象的创建,必须使用字段注入(想想Android中的Activity或Fragment)。如果某个(非匕首意识)框架正在创建我的对象并处理它,我别无选择,只能在收到实例后手动注入它。
Rule 1: MUST use field injection if I don't control creation of the object (think Activity or Fragment in Android). If some (non-dagger aware) framework is creating my object and handles it to me I have no choice but to inject it manually after I receive the instance.
规则2:如果该类是/可能在另一个不使用Dagger 2 的项目中使用,则必须使用构造函数注入。如果其他项目不使用Dagger,则他们无法使用DI,因此用户必须使用 new
以旧方式创建对象。
Rule 2: MUST use constructor injection if the class is/may be used in another project that does not use Dagger 2. If the other project(s) do not use Dagger they cannot use DI so the user have to create the object the "old" way using new
.
规则3:使用类层次结构时PREFER构造函数注入,因为它更容易创建单元测试。
澄清:
考虑以下使用现场注入的结构:
Considering the following structure that uses field injection:
package superclass;
public class SuperClass {
@Inject
HttpClient mHttpClient;
...
}
。
package differentpackage;
public class SubClass extends SuperClass {
public SubClass() {
}
}
当我在目录 test / java / differentpackage SubClass
创建单元测试时$ c>我别无选择,只能调出整个DI基础设施,以便能够注入 HttpClient
。相反,如果我像这样使用构造函数注入:
When I am creating unit test for SubClass
in directory test/java/differentpackage
I have no choice but to bring up the entire DI infrastructure in order to be able to inject the HttpClient
. In contrast, if I was using constructor injection like this:
public class SuperClass {
private final HttpClient mHttpClient;
@Inject
public SuperClass(HttpClient httpClient) {
mHttpClient = httpClient;
}
}
在我的单元测试中我可以简单地说:
in my unit test I could simply:
HttpClient mockHttp = mock(HttpClient.class);
Subclass tested = new Subclass(mockHttp);
// tests
所以基本上现在我处于另一个极端:我倾向于主要依靠构造函数注射并仅在规则1适用时使用场注射。
我对构造函数注入的唯一问题是,对于'end'类构造函数有时会变得非常重载参数,它们看起来像这样冗长和丑陋:
So basically now I am in the other extreme: I tend to rely mostly on constructor injections and use field injections only when 'Rule 1' applies.The only 'problem' that I have with the constructor injects is that for 'end' classes constructors sometimes become quite overloaded with parameters and they look verbose and ugly like this:
@Inject
public ModelMainImpl(@Named("app version") String appVersion,
AppPrefs appPrefs,
LoginPrefs loginPrefs,
@ForApplication Context appContext,
NetworkInfoProvider networkInfoProvider,
AndroidEventPoster androidEventPoster,
Session session,
ForgeExchangeManager exchangeManager,
HttpFunctionality httpFunctionality,
@Named("base url") String baseUrl,
@Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer
) {
伙计们,w帽子是您在构造函数和字段注入之间进行选择的规则吗?我错过了什么,我的逻辑中是否有错误?
Guys, what are your rules to choose between constructor and field injects? I am missing something, are there errors in my logic?
推荐答案
使用构造函数注入。如果不能,请使用属性注入。
Use constructor injection. if you can't, use property injection.
规则1似乎没问题,就像装饰或属性一样,你可以使用Property(field)注入。
Rule 1 seems ok, like decorations or attributes you can use Property(field) injection.
规则2似乎没问题,因为谁使用你的类他们必须遵循你的构造函数。他们可能不知道他们也必须为你的财产提供服务。
Rule 2 seems ok, because who uses your class they have to follow your constructor. They may not know they have to intilaize your property also.
规则3这不仅对单元测试有利。应用Single Responsibilty是有好处的。你可以更容易地看到你的对象图。否则你将用属性隐藏它。
Rule 3 It's not just good for unit test. It's good for applying Single Responsibilty. It's easier to see your object graph.Otherwise you will hide it with property.
如果我们提出你的问题,是的,你的构造函数中有很多参数。但解决方案不是属性注入。您可以重构代码并使用
If we come in your question, yes there a lot of parameters in your constructor. But the solution is not property injection. You can refactor your code and use aggregate services
这篇关于匕首2:何时使用构造注射以及何时使用注射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!