SpringBoot 依赖注入的优雅实现

简介: SpringBoot 依赖注入的优雅实现

前言

很多时候,我们在使用IDEA时,会发现注解@Autowired依赖注入 对于字段注入是不被推荐的,那么我们今天就来聊一下,作为Spring的特性之一的依赖注入,是如何优雅的实现的。

依赖注入,分为,字段注入、setter方法注入、构造器注入三种方式,那么我们就来聊一下,其中三者的好处,以及如何更好地选择使用。

理论上来说可以使用任何一个,它们的结果完全相同。但是,基于易用性,可读性,编码标准或更好的编码实践,有一定的差异。

字段注入

@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%的时间维护软件。可读性提高了软件的可维护性。

对所有三种方式的应用的可读性进行度量可见:

字段注入:最好的。更少的代码。重点是业务逻辑。

构造器注入:更好。构造函数在视觉上与方法分开。

Setter注入:最糟糕的。添加了4个实例方法。造成极差的可读性。

不变性

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

如果我们从不变性的角度看上面的代码示例:

构造函数注入:支持不变性。

setter注入:可变。

字段注入:可变。

状态安全性

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

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

如果我们从状态安全性的角度看上面的代码示例:

构造函数注入:状态安全。该对象被实例化为完整状态或完全不被实例化。

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
   //
}

Setter注入:不好。它添加了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
   //
}

对于大量依赖的情况下,无疑,字段注入是更该推荐的。但是,实际上对于我们程序的设计来说,不会出现太多的依赖。程序设计的原则之一是单一责任原则。

问题出现频率

基于大多数程序员开发的实际研究发现,使用字段注入,太依赖Spring容器,很多时候,会发生NullPointerException。而且,从设计来说,本身不应该过度的依赖容器,而应该保持独立。因此,字段注入在这种形势下,是不是被推荐的。

总结

根据上面的代码示例和我们的分析,很明显,基于构造的依赖注入在所有情况下始终表现得更好。构造函数注入是最佳选择。

注意:所有设计原则或更好的编码标准以及我们在此处讨论的内容都只是准则,而不是规则。

目录
相关文章
|
30天前
|
Java 容器 Spring
SpringBoot:详解依赖注入和使用配置文件
SpringBoot:详解依赖注入和使用配置文件
|
30天前
|
前端开发 Java API
Spring Boot之Spring MVC基于注解的控制器(RequestMapping注解类型 重定向与转发 依赖注入)
Spring Boot之Spring MVC基于注解的控制器(RequestMapping注解类型 重定向与转发 依赖注入)
51 0
|
30天前
|
Java 容器 Spring
【SpringBoot:详解依赖注入和使用配置文件】
【SpringBoot:详解依赖注入和使用配置文件】
18 2
|
10月前
|
Java 开发者 Spring
springboot依赖注入的几种方式
springboot依赖注入的几种方式
242 0
|
SQL XML Java
简单理解springboot的依赖注入
依赖注入,Dependency Injection,简称DI,是spring中的核心技术,此技术贯穿Spring全局,是必须要熟练掌握的知识点。在本文中,我们将要深入研究spring中的IOC和DI,理解核心思想,并学会如何在spring boot中使用基于java和注解的方式正确使用DI来创建spring应用程序。控制反转 IOC要理解DI,首先需要理解spring的核心思想之一,控制反转(In
1595 0
简单理解springboot的依赖注入
|
XML Java 程序员
Spring Boot2.x-05Spring Boot基础-使用注解完成依赖注入
Spring Boot2.x-05Spring Boot基础-使用注解完成依赖注入
86 0
Spring Boot2.x-05Spring Boot基础-使用注解完成依赖注入
Java:SpringBoot集成JWT实现token验证
Java:SpringBoot集成JWT实现token验证
381 0
Java:SpringBoot集成JWT实现token验证
|
前端开发 小程序 安全
微信小程序+Springboot实现宠物医院管理系统
本项目基于微信小程序开发实现了宠物医院管理系统的前端页面,基于Springboot+Mybatis实现了宠物医院管理系统的后台系统,采用前后端分离开发的模式来开发实现。功能齐全,操作简洁,技术性完整,页面简洁大方。其中后台管理模块主要包含有: 资料管理:个人资料管理、宠物资料管理、公告管理、医院资料管理、职工资料管理、住院资料管理、病历资料管理 预约管理:挂号预约、洗美预约、挂号预约、洗美预约 记录管理:诊断记录、洗美记录、支付记录 登陆、退出、个人信息修改、修改密码等功能 前端主要包含的功能模块有: 用户在线预约挂号等 查看医院公告信息
346 0
|
SQL Java
Java:Springboot整合PageHelper实现分页
Java:Springboot整合PageHelper实现分页
249 0
|
前端开发 Java Spring
Java:SpringBoot实现文件上传
Java:SpringBoot实现文件上传
249 0