欢迎使用Spring Dependency Injection –字段,设置器,构造函数注入教程。 了解场注入 , 二传手注入和构造函数注入之间的区别。 借助代码示例,我们将看到使用每个示例的好处以及为什么选择一个而不是另一个。

有关Spring依赖注入的更多信息:

  • Spring Setter依赖注入示例
  • Spring构造函数依赖注入示例
  • Spring字段依赖注入示例
  • Spring依赖注入和控制反转

总览

在Spring框架中,依赖注入分为三种类型。 它们是场注入 , setter注入和构造器注入 。 您可以绝对使用它们中的任何一个,它们的结果完全相同。 但是,基于易用性,可读性,编码标准或更好的编码实践,几乎没有差异。 在我们Swift了解这些差异之前,我们将了解所有三种类型的依赖注入 。

基于字段的依赖注入

@Component  public class MyClass { 
     @Autowired private DogsController controller; 
     @Autowired private DogsService service; 
     @Autowired private DogsDao dao; 
     @Autowired private ApplicationProperties properties; 
     //... 
     // Business methods 
     //  }

基于Setter的依赖注入

@Component  public class MyClass { 
     private DogsController controller; 
     private DogsService service; 
     private DogsDao dao; 
     private ApplicationProperties properties; 
     @Autowired 
     public void setController(DogsController controller) { 
         this .controller = controller; 
     } 
     @Autowired 
     public void setService(DogsService service) { 
         this .service = service; 
     } 
     @Autowired 
     public void setDao(DogsDao dao) { 
         this .dao = dao; 
     } 
     @Autowired 
     public void setProperties(ApplicationProperties properties) { 
         this .properties = properties; 
     } 
     //... 
     // Business methods 
     //  }

基于构造函数的依赖注入

@Component  public class MyClass { 
     private DogsController controller; 
     private DogsService service; 
     private DogsDao dao; 
     private ApplicationProperties properties; 
     @Autowired 
     public MyClass(DogsController controller, DogsService service, DogsDao dao, ApplicationProperties properties) { 
         this .controller = controller; 
         this .service = service; 
         this .dao = dao; 
         this .properties = properties; 
     } 
     //... 
     // Business methods 
     //  }

我们具有所有三种类型的依赖项注入的代码参考。 让我们在面向对象设计原则的一些重要方面进行评估。

可读性

可读性是人类对一个软件程序或一个软件程序的理解程度的判断。 开发人员花费30%的时间编写软件,并花费70%的时间维护软件。 可读性提高了软件的可维护性。 当开发人员查看课程时,他/她应该能够Swift专注于课程的重要部分,而不会被样板代码或其他框架组件所分散。

让我们对所有三个应用可读性度量

  • 现场注入 :最好的。 更少的样板代码。 重点是业务逻辑。
  • 构造函数注入 :更好。 构造函数在视觉上与方法分开。
  • 二传手注射:最糟糕。 添加了4个实例方法。 从业务方法中删除焦点。

用软件编程的术语来说,如果对象在创建后不能被修改,则称其为不可变 。 不变性是良好的面向对象编程的重要原则。 不变性为类带来了线程安全性,状态安全性和可读性。

如果我们从不变性的角度看上面的例子。

  • 构造函数注入 :支持不变性。
  • Setter注入 :无固定性。
  • 场注入 :无固定性。

国家安全

对象很可能由使用者或基础框架实例化。 对象本身应为实例化器提供规则或指导,以便他们将以正确的状态调用对象。 如果对象没有规定这种状态安全性,则有可能将对象实例化为不完整或不正确的状态。

注意 :以上所有示例都是状态安全的,因为Spring正在解析它们的依赖项,并且Spring将正确初始化所有字段,这些字段是@Autowired一部分。 但是某些使用者可能会使用new关键字实例化您的对象。 我们应该研究Spring框架之外的状态安全性。

让我们将State Safety措施应用于我们看到的所有示例。

  • 构造函数注入 :状态安全。 该对象被实例化为完整状态或完全不被实例化。
  • setter注入 :消费者使用无参数构造函数。 而且可能会错过调用设置器之一或两次以不同的值调用相同的设置器(复制粘贴错误)
  • 字段注入 :使用者使用无参数构造函数。 没有有效的方法来设置对象的状态。 唯一的选择是使用反射设置私有字段。

实例字段太多

让我们考虑具有6、7或更多字段的对象的情况。 当您将上述示例用于大量字段时,会发生什么情况。

场注入 :看起来仍然更好,而且可读性强。 依赖项被隔离在一个地方。

@Component  public class MyClass { 
     @Autowired private Service1 service1; 
     @Autowired private Service2 service2; 
     @Autowired private Service3 service3; 
     @Autowired private Service4 service4; 
     @Autowired private Service5 service5; 
     @Autowired private Service6 service6; 
     @Autowired private Service7 service7; 
     @Autowired private Service8 service7;     
     //... 
     // Business methods 
     //  }

构造函数注入 :丑陋! 构造函数注入确实看起来很丑。 对于消费者来说也不容易使用。

@Component  public class MyClass { 
     private Service1 service1; 
     private Service2 service2; 
     private Service3 service3; 
     private Service4 service4; 
     private Service5 service5; 
     private Service6 service6; 
     private Service7 service7; 
     private Service8 service7; 
     @Autowired 
     public MyClass(Service1 service1, Service2 service2, Service3 service3, Service4 service4, Service5 service5, Service6 service6, Service7 service7, Service8 service71) { 
         this .service1 = service1; 
         this .service2 = service2; 
         this .service3 = service3; 
         this .service4 = service4; 
         this .service5 = service5; 
         this .service6 = service6; 
         this .service7 = service7; 
         this .service7 = service71; 
     }  //... 
     // Business methods 
     //  }

二传手注射 :不好。 它添加了8个额外的实例方法,仅用于设置依赖项。

@Component  public class MyClass { 
     private Service1 service1; 
     private Service2 service2; 
     private Service3 service3; 
     private Service4 service4; 
     private Service5 service5; 
     private Service6 service6; 
     private Service7 service7; 
     private Service8 service7; 
     @Autowired 
     public void setService1(Service1 service1) { 
         this .service1 = service1; 
     } 
     @Autowired 
     public void setService2(Service2 service2) { 
         this .service2 = service2; 
     } 
     @Autowired 
     public void setService3(Service3 service3) { 
         this .service3 = service3; 
     } 
     @Autowired 
     public void setService4(Service4 service4) { 
         this .service4 = service4; 
     } 
     @Autowired 
     public void setService5(Service5 service5) { 
         this .service5 = service5; 
     } 
     @Autowired 
     public void setService6(Service6 service6) { 
         this .service6 = service6; 
     } 
     @Autowired 
     public void setService7(Service7 service7) { 
         this .service7 = service7; 
     } 
     @Autowired 
     public void setService7(Service8 service7) { 
         this .service7 = service7; 
     } 
     //... 
     // Business methods 
     //  }

我们是否应该考虑“实例字段太多”?

通过检查 “ 太多实例字段” ,我们发现“ 字段注入”是最好的。 真正的问题是,我们是否应该重视太多领域的问题?

答案是不。 我们所有人都喜欢并遵循单一责任原则 。 如果您的班级依赖太多东西,则说明设计不正确。 采用更好的设计,您将不会看到这些问题。 我们不应该支持不良的设计案例。 因此,我们将不重视“实例字段太多”的情况。

在特殊的情况下,不可避免的是有太多字段,而丑陋的构造函数是一个大问题,您应该致电并进行Field Injection 。

结论

根据上面的代码示例和事实,很明显, 基于构造的依赖注入在所有情况下始终表现得更好。 即使我们从Spring Dependency Injection的角度来看我们的课程,构造函数注入仍然是最佳选择。

注意:所有设计原则或更好的编码标准以及我们在此处讨论的内容都只是准则,而不是规则。 您只是足够聪明,可以接听电话并证明您要走的路。

快乐编码!

翻译自: https://www.javacodegeeks.com/2019/02/field-setter-constructor-injection.html