Spring依赖注入DI之三种依赖注入类型详解

 更新时间:2023年09月13日 09:04:27   作者:黄泥川水猴子  
这篇文章主要介绍了Spring依赖注入DI之三种依赖注入类型详解,通过 @Autowired 注解,字段注入的实现方式非常简单而直接,代码的可读性也很强,事实上,字段注入是三种注入方式中最常用、也是最容易使用的一种,需要的朋友可以参考下

 Spring依赖注入

在这里插入图片描述

字段注入

首先,我们可以使用字段注入。想要在一个类中通过字段的形式注入某个对象,可以采用这样的方式:

public class ClientService { 
    @Autowired 
    private HealthRecordService healthRecordService; 
    public void recordUserHealthData() { 
        healthRecordService.recordUserHealthData(); 
    } 
}

可以看到,通过 @Autowired 注解,字段注入的实现方式非常简单而直接,代码的可读性也很强。事实上,字段注入是三种注入方式中最常用、也是最容易使用的一种。但它也是三种注入方式中最应该避免使用的。就像开篇说的,我们在 IDEA 中使用字段注入时会遇到“Field injection is not recommended”的提示。你知道为什么吗?原因有三点。

问题一、

字段注入的最大问题是对象的外部可见性。在前面的 ClientService 类中,我们通过定义一个私有变量 HealthRecordService 来注入该接口的实例。显然,这个实例只能在 ClientService 类中被访问,脱离了容器环境我们无法访问这个实例,来看下面这段代码:

ClientService clientService = new ClientService(); 
clientService.recordUserHealthData (); 

执行这段代码的结果就是抛出一个 NullPointerException 空指针异常,原因就在于无法在 ClientService 的外部实例化 HealthRecordService 对象。采用字段注入,类与容器的耦合度过高,我们无法脱离容器来使用目标对象。如果编写测试用例来验证 ClientService 类的正确性,那么想要使用 HealthRecordService 对象,就只能使用反射的方式,这种做法实际上是不符合 JavaBean 开发规范的,而且可能一直无法发现空指针异常的存在。

问题二、

我们无法设置需要注入的对象为 final,也无法注入那些不可变对象,final类型的变量在调用class的构造函数的这个过程当中就得初始化完成,这个是基于字段的依赖注入做不到的地方,只能使用基于构造函数的依赖注入的方式.

问题三、

字段注入的第三个问题是可能导致潜在的循环依赖,即两个类之间互相进行注入,例如下面这段示例代码:

public class ClassA { 
    @Autowired 
    private ClassB classB; 
} 
public class ClassB { 
    @Autowired 
    private ClassA classA; 
} 

这里的 ClassA 和 ClassB 发生了循环依赖。上述代码在 Spring 中是合法的,容器启动时并不会报任何错误,而只有在使用到具体某个 ClassA 或 ClassB 时才会报错。

问题四、

无法对注入的属性进行安全检查 在程序启动的时候无法拿到这个类,只有在真正的业务使用的时候才会拿到,若注入的是null,因为不调用将一直无法发NullPointException的存在。 或者想在属性注入的时候,增加验证措施,也无法办到。

基于以上四点,无论是 IDEA,还是 Spring 官方,都不推荐开发人员使用字段注入这种注入模式,而是推荐构造器注入。

在面试中,针对字段注入,请记住它主要的三点缺陷:不具备外部可见性、会导致循环依赖,以及无法注入不可变对象

构造器注入

@Controller
@RequestMapping("employee")
public class EmployeeController {
    private final EmployeeMapper employeeMapper;
    @Autowired
    public EmployeeController(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
}

优点:

  • 保证依赖不可变(final关键字)。
  • 保证依赖不为空(省去了我们对其检查)。
  • 保证返回客户端(调用)的代码的时候是完全初始化的状态。
  • 避免了循环依赖。
  • 提升了代码的可复用性。
  • 可以明确成员变量的注入顺序。

缺点:

  • 当注入参数较多时,代码臃肿。

set方法注入

@Controller
@RequestMapping("employee")
public class EmployeeController {
    private EmployeeMapper employeeMapper;
    @Autowired
    public void setEmployeeMapper(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
}

优点:

  • 相比构造器注入,set注入类似于选择性注入。
  • 允许在类构造完成后重新注入。

缺点: 暂无

到此这篇关于Spring依赖注入DI之三种依赖注入类型详解的文章就介绍到这了,更多相关Spring依赖注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java获取文件的hash值(SHA256)两种方式

    Java获取文件的hash值(SHA256)两种方式

    这篇文章主要给大家介绍了关于Java获取文件hash值(SHA256)的两种方式,SHA256是一种哈希算法,它是不可逆的,也就是说无法解密,需要的朋友可以参考下
    2023-09-09
  • Java中获取当前路径的几种方法总结

    Java中获取当前路径的几种方法总结

    这篇文章主要介绍了Java中获取当前路径的几种方法总结的相关资料,需要的朋友可以参考下
    2017-02-02
  • 谈谈对Java中的volatile的理解

    谈谈对Java中的volatile的理解

    这篇文章主要介绍了对Java中的volatile的理解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Java数字签名算法DSA实例详解

    Java数字签名算法DSA实例详解

    这篇文章主要介绍了Java数字签名算法DSA,结合实例形式分析了Java数字签名算法DSA具体定义与使用技巧,需要的朋友可以参考下
    2018-05-05
  • Java中static变量作用和用法详解

    Java中static变量作用和用法详解

    Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问.下面我们来详细了解一下吧
    2019-06-06
  • Java输入处理的常见错误小结

    Java输入处理的常见错误小结

    在 Java 编程中,输入处理是一个基础但又复杂的任务,尤其是在涉及到与用户交互时,本文将对 Java 输入处理的基本机制进行详细解析,需要的可以了解下
    2024-11-11
  • Java实现解析并生成xml原理实例详解

    Java实现解析并生成xml原理实例详解

    这篇文章主要介绍了Java实现解析并生成xml原理实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 基于Java Swing制作一个Pong小游戏

    基于Java Swing制作一个Pong小游戏

    《Pong》是美国雅达利公司(ATARI)开发的视频游戏,该作模拟了两个打乒乓球的人,就是在两条线中间有一个点在动,操纵器就是一个摇杆上有一个按钮的那种。本文就来用Java Swing制作一个Pong小游戏吧
    2023-01-01
  • 详解Java中的do...while循环语句的使用方法

    详解Java中的do...while循环语句的使用方法

    这篇文章主要介绍了Java中的do...while循环语句的使用方法,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10
  • Java实现二维码生成的代码方法

    Java实现二维码生成的代码方法

    这篇内容分享了JAVA实现二维码生成的实例代码,对此有需要的朋友们可以测试参考下。
    2018-07-07

最新评论