简体   繁体   English

Spring依赖注入

[英]Spring Dependency Injection

I am learning Spring using Spring Recipes. 我正在使用Spring Recipes学习Spring。 As of now I understood that we can inject dependencies using Setter Injection or Injecting via constructor. 截至目前,我了解到我们可以使用Setter Injection或Injecting via constructor注入依赖项。 My question is, in real world applications what method is used more often and why? 我的问题是,在现实世界的应用程序中,更常使用哪种方法,为什么? I know its a subjective question but I cant think of a better place than this site to get perfect insights. 我知道这是一个主观问题,但我不能想到一个比这个网站更好的地方来获得完美的见解。 Thanks again. 再次感谢。

Constructor injection is preferable over setter injection because it clearly defines what dependencies are needed, and forces you to provide them before you can create an instance of the class. 构造函数注入优于setter注入,因为它清楚地定义了所需的依赖项,并强制您在创建类的实例之前提供它们。 With setter injection, the caller has to figure out what dependencies are needed, and can lead to situations where the caller fails to inject all the necessary dependencies. 使用setter注入时,调用者必须确定需要哪些依赖项,并且可能导致调用者无法注入所有必需的依赖项。

However, there are cases where you'll need to use setter injection, such as dealing with objects that only have a default constructor, or setting dependencies where there might be a bi-directional relationship. 但是,在某些情况下,您需要使用setter注入,例如处理只有默认构造函数的对象,或者设置可能存在双向关系的依赖项。

When in doubt, try to use constructor injection, and only fall back to setters when needed. 如有疑问,请尝试使用构造函数注入,并在需要时仅回退到setter。

Constructor injection is considered better than setter injection because of many reasons since constructor injection ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state. 构造函数注入被认为比setter注入更好,原因很多,因为构造函数注入确保满足所有必需属性,并且根本无法在无效状态下实例化对象。 Please see this post for an example: http://www.redcode.nl/blog/2010/09/setter-vs-constructor-injection/ 请参阅此帖子以获取示例: http//www.redcode.nl/blog/2010/09/setter-vs-constructor-injection/

The other answers are already very clean on the fact, that Constructor injection is more save, in terms of forget to set a field. 其他答案已经非常干净了,就忘记设置字段而言,Constructor注入更省。 -- You can just not create the instance without the field. - 您可以不在没有字段的情况下创建实例。 So one advice from this statements could be: use constructor injection for mandatory fields and setter or field injection for optional fields. 因此,此语句的一个建议可能是:对必填字段使用构造函数注入,对可选字段使用setter或field injection。

And Constructor Injection has two other impacts: 构造函数注入还有两个其他影响:

  • the fields can be final - ( I like final fields, because the make understanding easier ) 字段可以是final - ( 我喜欢最终字段,因为make理解更容易
  • you can not build circles of classes. 你不能建立类的圈子。 (Ab and Ba) - Spring can not instantiate this construction. (Ab和Ba) - Spring无法实例化这种结构。 (*From a architetural point of view, I think this is a pro of constructor injection, not a con) (*从架构的角度来看,我认为这是构造函数注入的专家,而不是con)

But on the other hand, if you use constructor injection you have to write a more code than necessary. 但另一方面,如果使用构造函数注入,则必须编写超出必要的代码。

public class FieldInjection {
  @Ressource //the same like @Autowired(required=true)
  private MyService myService;
}

is much shorter than: 比以下要短得多:

public class MethodInjection {      
  private final MyService myService;

  public MethodInjection(final MyService myService) {
     assert(myService != null);
     this.myService = myService;
  }
}

The autors of the other answers will hate me for that statement. 其他答案的主持人会因为这个陈述而讨厌我。

I personally believe that when you have a Class, that is only used as a Spring Bean (but not without Spring) then you can use field Injection without that safety doubt! 个人认为,当你有一个Class时,它只用作Spring Bean(但不是没有Spring),那么你可以使用现场注入而不会出现安全问题! - Because Spring will only put the Bean in its lifecycle if it can set all fields annotated by @Ressource or @Autowired(required=true) . - 因为如果可以设置由@Ressource@Autowired(required=true)注释的所有字段@Autowired(required=true) Spring只会将Bean置于其生命周期中。 Because of this I prefer field injection because it makes my faster (less to write and less to read ). 因此,我更喜欢场注入,因为它使我更快(写入更少,阅读更少 )。 And for all initialialization stuff, I use @PostConstruct . 对于所有初始化的东西,我使用@PostConstruct (Of course you can not use the fields in the constructor. And you can not really mix them both.) - That ties my Application much stronger to an IOC container than constructor injetion, but this is not a problem for my usecase. (当然你不能使用构造函数中的字段。并且你不能真正地将它们混合在一起。) - 这使得我的应用程序比构造函数注入更强大于IOC容器,但这对我的用例来说不是问题。 - May you have a look at EJB 3.1 standard, they do not have constructor injection at all. - 您可以查看EJB 3.1标准,它们根本没有构造函数注入。

There are pros and cons to each way. 每种方式都有利弊。 I would argue that constructor based dependency injection is less error prone, because you are imposing certain rules and telling your class which dependencies its methods needs. 我认为基于构造函数的依赖注入不容易出错,因为你强加了某些规则并告诉你的类其方法需要哪些依赖项。 More importantly, constructor injection enforces the order of initialization and prevents circular dependencies. 更重要的是,构造函数注入强制执行初始化顺序并防止循环依赖。 With setter injection it is not clear in which order things need to be instantiated and when the wiring is done. 使用setter注入时,不清楚需要实例化的事件以及布线何时完成。

On the other hand, there are reasons why setter injection wins. 另一方面,有成因证注射获胜的原因。 Unit testing is always easier if constructors are simple and do less, or do nothing at all. 如果构造函数很简单并且做得更少,或者什么也不做,那么单元测试总是更容易。 Besides, not all methods of a class require the same dependencies. 此外,并非所有类的方法都需要相同的依赖项。 If you use the Spring container to inject your dependencies, then you don't always have to worry about this because the Spring container will automatically call your setters for you if you configure it correctly. 如果您使用Spring容器注入依赖项,那么您并不总是担心这一点,因为如果您正确配置它,Spring容器将自动为您调用setter。

I prefer constructor injection myself. 我更喜欢自己构造注射。 I've been using Spring since 2005. 我从2005年开始使用Spring。

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

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