Spring注解依赖注入的三种方式的优缺点以及优先选择

当我们在使用依赖注入的时候,通常有三种方式:

1.通过构造器来注入;

2.通过setter方法来注入;

3.通过filed变量来注入;

那么他们有什么区别吗?应该选择哪种方式更好?

 

代码示例:

Constructor

 1 private DependencyA dependencyA;
 2 private DependencyB dependencyB;
 3 private DependencyC dependencyC;
 4  
 5 @Autowired
 6 public DI(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC) {
 7     this.dependencyA = dependencyA;
 8     this.dependencyB = dependencyB;
 9     this.dependencyC = dependencyC;
10 }

Setter

 1 private DependencyA dependencyA;
 2 private DependencyB dependencyB;
 3 private DependencyC dependencyC;
 4  
 5 @Autowired
 6 public void setDependencyA(DependencyA dependencyA) {
 7     this.dependencyA = dependencyA;
 8 }
 9  
10 @Autowired
11 public void setDependencyB(DependencyB dependencyB) {
12     this.dependencyB = dependencyB;
13 }
14  
15 @Autowired
16 public void setDependencyC(DependencyC dependencyC) {
17     this.dependencyC = dependencyC;
18 }

Field

1 @Autowired
2 private DependencyA dependencyA;
3  
4 @Autowired
5 private DependencyB dependencyB;
6  
7 @Autowired
8 private DependencyC dependencyC;

 

 

三种方式的区别小结:

1.基于constructor的注入,会固定依赖注入的顺序;该方式不允许我们创建bean对象之间的循环依赖关系,这种限制其实是一种利用构造器来注入的益处 - 当你甚至没有注意到使用setter注入的时候,Spring能解决循环依赖的问题;

2.基于setter的注入,只有当对象是需要被注入的时候它才会帮助我们注入依赖,而不是在初始化的时候就注入;另一方面如果你使用基于constructor注入,CGLIB不能创建一个代理,迫使你使用基于接口的代理或虚拟的无参数构造函数。

3.相信很多同学都选择使用直接在成员变量上写上注解来注入,正如我们所见,这种方式看起来非常好,精短,可读性高,不需要多余的代码,也方便维护;

 

缺点:

1.当我们利用constructor来注入的时候,比较明显的一个缺点就是:假如我们需要注入的对象特别多的时候,我们的构造器就会显得非常的冗余、不好看,非常影响美观和可读性,维护起来也较为困难;

2.当我们选择setter方法来注入的时候,我们不能将对象设为final的;

3.当我们在field变量上来实现注入的时候

    a.这样不符合JavaBean的规范,而且很有可能引起空指针;

    b.同时也不能将对象标为final的;

  c.类与DI容器高度耦合,我们不能在外部使用它;

    d.类不通过反射不能被实例化(例如单元测试中),你需要用DI容器去实例化它,这更像集成测试;

    ... etc.

 

来自Spring官方文档的建议:  
在Spring 3.x 中,Spring团队建议我们使用setter来注入:

大致是说大量的构造器参数会显得非常笨重,尤其是当属性是可选的时候。setter方法可以使类的对象在后来重新配置或者重新注入。提供所有的依赖意味着对象总是返回一个完全初始化状态的client客户端(调用)。缺点是对象变得不那么适合重新配置和重新注入。

 

而在Spring 4.x 中,Spring团队不再建议我们使用setter来注入,改为了constructor:

Spring团队通常建议使用构造器来注入,因为它允许一个应用程序组件实现为不可变对象,并确保所需的依赖项不是空。此外构造器注入组件总是返回一个完全初始化状态的client客户端(调用)。附注,大量的构造函数参数是一个糟糕的代码习惯,看起来也很坏,这意味着类可能有太多的责任,应该被重构,以更好地解决适当的关注点分离。

setter方法只应该主要的用在可以在类中指定合理的默认值的可选的依赖关系。否则,用到依赖的所有地方都应该进行非空检查。setter注入的一个好处是,setter方法使类的对象可以在之后重新配置或者重新注入。

(以上是本人的渣渣英语翻译结合有道得来。。大佬看到请轻喷)

 

接下来插播一条Spring 4.3 的新特征:

在Spring 4.3 以后,如果我们的类中只有单个构造函数,那么Spring就会实现一个隐式的自动注入,上代码:

之前:

 1 @Service
 2 public class FooService {
 3 
 4     private final FooRepository repository;
 5 
 6     @Autowired
 7     public FooService(FooRepository repository) {
 8         this.repository = repository
 9     }
10 }

在Spring 4.3 之后:

1 @Service
2 public class FooService {
3 
4     private final FooRepository repository;
5 
6     public FooService(FooRepository repository) {
7         this.repository = repository
8     }
9 }

如我们所见,我去掉了构造器上的@Autowired注解,经测试后发现,程序能正常运行,repository的依赖也被成功注入了,当时感觉就很amazing。。有兴趣的同学可以试试~

 

总结:

1.强制性的依赖性或者当目标不可变时,使用构造函数注入(应该说尽量都使用构造器来注入

2.可选或多变的依赖使用setter注入(建议可以使用构造器结合setter的方式来注入

3.在大多数的情况下避免field域注入(感觉大多数同学可能会有异议,毕竟这个方式写起来非常简便,但是它的弊端确实远大于这些优点

4.Spring 4.3+ 的同学可以试一试构造器的隐式注入,采用此方式注入后,使得我们的代码更优雅,更独立,减少了对Spring的依赖性。

 

ps: 转载请标注出处谢谢。

转载于:https://www.cnblogs.com/chansblogs/p/8343930.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

seo超强外部链接、内部链接技巧

轮链-混链对做内外链都是非常有效果的! 外连,之于大家并不陌生,增加外链的方法也海了去,如软文推广、博客推广、友情链接等等等等,在这里我就不再累述,最近在一些文章里看到轮链和混链的SEO优化技巧&#x…

王道操作系统考研笔记——1.1.5 中断和异常

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 文章目录1.1.5 中断和异常1.1.5.1 中断机制的诞生1.1.5.2 中断的概念和作用1.1.5.3 中断的分类1.1.5.4 小结1.1.5 中断和异常 知识总览 1.1.5.1 中断机制的诞…

LR+Jenkins实践思路

思路:在Loadrunner的安装bin目录下有Loadrunner Control模块的启动程序 “Wlrun.exe”,想利用Jenkin的 windows的batch命令持续构建一个任务,自动启动运行场景,且把结果发给analysis 通过Batch来调用LR场景: Loadrunne…

王道操作系统考研笔记——2.1.1 进程的定义、组成、组织方式和特征

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 文章目录2.1.1 进程的定义、组成、组织方式和特征2.1.1.1 进程的定义2.1.1.2 进程的定义2.1.1.3 进程的组成2.1.1.4 进程的组织2.1.1.5 链接方式2.1.1.6 索引方…

服务器换账号登陆不了怎么办,怎么切换账号 更换账号 注册新的账号小技巧分享给你...

很多玩家喜欢多尝试几种玩法,那么万国觉醒怎么切换账号?切换账号后玩家如何再重新登入游戏?如何在多个账号中快速切换?今天小编就跟大家说说万国觉醒快速切换账号登入游戏的技巧。一、切换账号介绍我们常说的切换账号有两种意思&a…

vue基本介绍

https://cn.vuejs.org/v2/guide/ Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既…

android控件的隐藏与显示

2019独角兽企业重金招聘Python工程师标准>>> visibility:显示 invisibility:不显示,不可见但是仍然占据空间 gone:不显示,不可见不占用空间 view.setVisibility();----设置值:0代表visibility&a…

《BI那点儿事》Microsoft 线性回归算法

Microsoft 线性回归算法是 Microsoft 决策树算法的一种变体,有助于计算依赖变量和独立变量之间的线性关系,然后使用该关系进行预测。该关系采用的表示形式是最能代表数据序列的线的公式。例如,以下关系图中的线是数据最可能的线性表示形式。 …

王道操作系统考研笔记——2.1.2 进程的状态和转换

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 2.1.2 进程的状态和转换 知识总览 2.1.2.1 三种基本状态 进程是程序的一次执行。在这个执行过程中,有时进程正在被CPU处理,有时又需要…

Java中抽象类和接口在概念、语法和应用上的区别和关系

2019独角兽企业重金招聘Python工程师标准>>> 春招开始了,盆友们都忙着准备笔试、准备面试,复习学过的知识点,当然我也不例外,在这里祝每一个"有心人"心想事成,梦圆2016,加油&#xff…

王道操作系统考研笔记——2.1.3 进程控制

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 2.1.3 进程控制 知识总览 2.1.3.1 进程控制的过程 进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实…

王道操作系统考研笔记——2.1.4 进程通信

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 2.1.4 进程通信 知识总览 2.1.4.1 什么是进程通信 顾名思义,进程通信就是指进程之间的信息交换。 进程是分配系统资源的单位(包括内…

关于设计模式——策略模式-Strategy Pattern

文章目录1 策略模式1.1 模拟鸭子1.2 设计原则1.3 整合行为1.4 模拟鸭子代码的代码1.5 动态设定行为1.6 重新查看整体1.7 继承和组合1.8 总结1.9 优劣期间应用场景2.0 参照资料1 策略模式 在我们什么都不会的情况下,我们先无需知道什么是策略模式,我们要…

python (3):wxPython打包app,报错

1,打包app报错 如图: 使用py2app,mac下打包成app。异常。程序直接退出。 没有详细的错误信息,client程序直接崩溃了。 2。原因 代码没有几行: #!/usr/bin/python # -*- coding: utf-8 -*- import wxapp wx.App(False…

.NET Framework 工具

您可以使用 .NET Framework 工具轻松创建、部署和管理面向 .NET Framework 的应用程序和组件。 此节中介绍的大部分 .NET Framework 工具将自动随 Visual Studio 一起安装。 (有关安装信息,请参阅 Visual Studio 下载。) 可以从命令行运行除程…

并发无锁队列学习(概念介绍)

1、前言 队列在计算机中很重要的一种数据结构,尤其在操作系统中。队列典型的特征是先进先出(FIFO),符合流水线业务流程。在进程间通信、网络通信之间常常採用队列做缓存,缓解数据处理压力。结合自己在工作中遇到的队列…

王道操作系统考研笔记——2.1.5 线程概念与多线程模型

文章目录2.1.5 线程概念与多线程模型2.1.5.1 线程的来源2.1.5.2 线程机制带来的变化2.1.5.3 线程的属性2.1.5.4 线程的实现方式2.1.5.5 多线程模型2.1.5.6 小结2.1.5 线程概念与多线程模型 2.1.5.1 线程的来源 在很久以前还没有引入进程之前,系统中的各个程序只能…

mybatis处理集合、循环、数组和in等语句的使用

2019独角兽企业重金招聘Python工程师标准>>> 在Mybatis的xml配置中使用集合,主要是用到了foreach动态语句。 foreach的参数:foreach元素的属性主要有 item,index,collection,open,separator&…

王道操作系统考研笔记——2.1.6 处理机调度的概念和层次

文章目录2.1.6 处理机调度的概念和层次2.1.6.1 调度的基本概念2.1.6.2 高级调度2.1.6.3 中级调度2.1.6.4 进程的挂起态和七状态模型2.1.6.5 低级调度2.1.6.6 三层调度的联系、对比2.1.6.7 小结2.1.6 处理机调度的概念和层次 知识总览 2.1.6.1 调度的基本概念 实际上&#xff…

CocoaPods详解之----使用篇

作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/18737437 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号wangzzstrive来支持我,谢谢! 一、什么是CocoaPods 1、为什…