【Java EE】依赖注入DI详解

文章目录

  • 🌴什么是依赖注入
  • 🍀依赖注入的三种方法
    • 🌸属性注入(Field Injection)
    • 🌸构造方法注入
    • 🌸Setter注入
    • 🌸三种注入优缺点分析
  • 🌳@Autowired存在的问题
  • 🌲解决@Autowired对应多个对象问题
  • 🍃@Autowird与@Resource的区别
  • ⭕总结

🌴什么是依赖注入

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象.

简单来说, 就是把对象取出来放到某个类的属性中

在⼀些⽂章中, 依赖注⼊也被称之为 “对象注⼊”, “属性装配”, 具体含义需要结合⽂章的上下⽂来理解

🍀依赖注入的三种方法

关于依赖注⼊, Spring也给我们提供了三种⽅式:

  1. 属性注⼊(Field Injection)
  2. 构造⽅法注⼊(Constructor Injection)
  3. Setter 注⼊(Setter Injection)

🌸属性注入(Field Injection)

属性注⼊是使⽤ @Autowired 实现的。

比如我们将StudentService类注⼊到StudentController类中.

StudentService.java代码如下:

@Service
public class StudentService {public void run() {System.out.println("StudentService启动");}
}

StudentController.java代码如下:

@RestController
public class StudentController {@Autowiredprivate StudentService studentService;public void run() {System.out.println("StudentController启动");studentService.run();}
}

获取StudentController中的run方法

@SpringBootApplication
public class SpringMvcApplication {public static void main(String[] args) {//获取spring上下文ApplicationContext context = SpringApplication.run(SpringMvcApplication.class, args);//从spring中获取对象StudentController studentController = context.getBean("studentController",StudentController.class);//使用spring对象studentController.run();}}

🌸构造方法注入

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所示:

@RestController
public class StudentController {private StudentService studentService;public StudentController() {}@Autowiredpublic StudentController(StudentService studentService) {this.studentService = studentService;}public void run() {System.out.println("StudentController启动");studentService.run();}}

注意事项:

  • 如果类只有⼀个构造⽅法,那么@Autowired注解可以省略;如果类中有多个构造⽅法,那么需要添加上@Autowired来明确指定到底使⽤哪个构造⽅法

🌸Setter注入

Setter注入和属性的Setter⽅法实现类似,只不过在设置set⽅法的时候需要加上@Autowired注解

@RestController
public class StudentController {private StudentService studentService;@Autowiredpublic void setStudentService(StudentService studentService) {this.studentService = studentService;}public void run() {System.out.println("StudentController启动");studentService.run();}}

🌸三种注入优缺点分析

属性注⼊

  • 优点: 简洁,使⽤⽅便;
  • 缺点:
    – 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指
    针异常)
    – 不能注⼊⼀个Final修饰的属性

构造函数注入

  • 优点:
    – 可以注⼊final修饰的属性
    – 注⼊的对象不会被修改
    – 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
    是在类加载阶段就会执⾏的⽅法.
    – 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

  • 缺点:
    – 注⼊多个对象时, 代码会⽐较繁琐

Setter注入

  • 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
  • 缺点:
    – 不能注⼊⼀个Final修饰的属性
    – 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险

🌳@Autowired存在的问题

当同⼀类型存在多个bean时,在使⽤@Autowired就会存在问题

比如我们有以下bean。

BeanFiguation.java代码如下:

@Configuration
public class BeanFiguation {@Beanpublic Student student1() {Student student = new Student();student.setId(11);student.setName("山高路远");student.setAge(11);return student;}@Beanpublic Student student2() {Student student = new Student();student.setId(22);student.setName("与君共勉");student.setAge(22);return student;}
}

StudentController.java代码如下:

@RestController
public class StudentController {@Autowiredprivate Student student;public void run() {System.out.println(student);}
}

当我们进行启动时:
在这里插入图片描述
报错的原因是,⾮唯⼀的 Bean 对象

🌲解决@Autowired对应多个对象问题

为了解决上述问题,Spring提供了以下4种解决⽅案:

  • bean对象名称与属性名相匹配
  • @Primary
  • @Qualifier
  • @Resource

第一种:bean对象名称与属性名相匹配
在这里插入图片描述
第二种:使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.

@Component
public class BeanConfig {@Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}

第三种:使⽤@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean的名称。

@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤

@Controller
public class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}

第四种:使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。

@Controller
public class UserController {@Resource(name = "user2")private User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}

🍃@Autowird与@Resource的区别

  • @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
  • @Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊. 相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。

⭕总结

感谢大家的阅读,希望得到大家的批评指正,和大家一起进步,与君共勉!

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

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

相关文章

动态库静态库linux

动态库静态库 静态库 静态库必须包含在可执行文件里,整个都要包含 缺点:消耗系统大,每个使用静态库的程序都要复制静态库(浪费内存) 影响使用场景: 在静态库内存小的时候,可以用来提升速度 制…

redis在Windows下设置静默启动

redis在Windows下设置静默启动 下载windows版redis,解压cmd命令行有窗口启动(这种启动方式,这个界面就不能关闭才会生效 注册成为服务,设置成开机启动或者手动启动(静默启动)清除缓存本地清除,直接打开redis-cli.exe本地远程连接清除缓存 下载…

投影矩阵(Projection Matrix)

在机器学习和数据分析中,投影矩阵是一个非常重要的工具,它主要用于将高维数据降维或者变换到新的坐标系中。这个过程通常被称为线性变换或投影。 过程: 假设我们有一个原始的高维数据集X,其中每一列代表一个特征,每一行…

Scala 03 —— Scala Puzzle 拓展

Scala 03 —— Scala Puzzle 拓展 文章目录 Scala 03 —— Scala Puzzle 拓展一、占位符二、模式匹配的变量和常量模式三、继承 成员声明的位置结果初始化顺序分析BMember 类BConstructor 类 四、缺省初始值与重载五、Scala的集合操作和集合类型保持一致性第一部分代码解释第二…

【C++】<入门>C++入门基础知识

C入门 1. 入门0. 本节知识点熟悉目的1. C关键字(C98) 2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.1 函数重载概念5.2 C支持函数重载的原理--名字修饰(name Ma…

Vue3从入门到实践:深度了解新组件

1.Teleport 概念:Teleport(传送门)是一个新的特性,用于在DOM中的任意位置渲染组件。它允许你将组件的内容渲染到DOM中的另一个位置,而不受组件层次结构的限制。 下面举出例子解释: 1.新建App.vue文件作…

RACE IPEMD:构建安全基石的密码学原理与实践

title: RACE IPEMD:构建安全基石的密码学原理与实践 date: 2024/4/16 16:53:56 updated: 2024/4/16 16:53:56 tags: IPEMD哈希算法SHA-1SHA-2/3消息摘要数字签名安全分析 前言 在当今信息爆炸的时代,数据安全和隐私保护变得尤为重要。密码学作为信息安…

Rust 构建跨平台 GUI 的新选择

在现代软件开发过程中,用户界面(GUI)的设计与实现是不可或缺的一环。随着Rust编程语言的崛起,其安全性、性能和并发特性使其成为开发高质量GUI应用的理想选择。relm框架,作为Rust生态中的一员,提供了一种声…

k8s的资源对象Deployment该如何使用?

k8s的资源对象Deployment该如何使用? Kubernetes(k8s)是一个开源的容器编排系统,用于自动化应用程序部署、扩展和管理。在k8s中,Deployment是管理Pod副本的一种方式,它确保了指定数量的Pod副本始终运行。本…

计算机视觉——基于OpenCV和Python进行模板匹配

模板匹配? 模板匹配是它允许在一幅较大的图像中寻找是否存在一个较小的、预定义的模板图像。这项技术的应用非常广泛,包括但不限于图像识别、目标跟踪和场景理解等。 目标和原理 模板匹配的主要目标是在一幅大图像中定位一个或多个与模板图像相匹配的…

最小生成树算法的实现c++

最小生成树算法的实现c 题目链接:1584. 连接所有点的最小费用 - 力扣(LeetCode) 主要思路:使用krusal算法,将边的权值进行排序(从小到大排序),每次将权值最小且未加入到连通分量中…

Linux下SPI设备驱动实验:向SPI驱动框架中加入字符设备驱动框架代码

一. 简介 前一篇文章编写了SPI设备驱动框架代码,文章如下: Linux下SPI设备驱动实验:SPI设备驱动框架编写-CSDN博客 本文继续SPI驱动代码的编写。向SPI驱动框架中加入字符设备驱动框架代码。 二. 向SPI驱动框架中加入字符设备驱动框架代码…

Cesium中实现镜头光晕

镜头光晕 镜头光晕 (Lens Flares) 是模拟相机镜头内的折射光线的效果,主要作用就是让太阳光/其他光源更加真实,和为您的场景多增添一些气氛。 Cesium 中实现 其实 Cesium 里面也是有实现一个镜头光晕效果的,添加方式如下,只是效…

Python教学入门:数字类型与字符串

字符串元素组成的序列 字符串元素组成的序列指的是字符串中的每个字符按照一定的顺序排列形成的序列。在 Python 中,字符串是由字符组成的有序序列(Sequence),每个字符在字符串中有其固定的位置(索引)&…

Android RecyclerView的LayoutManager配置

RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。 LayoutManager介绍 RecyclerView可以通过setLayoutManager设置布局管理器,该方法的源码如下: /*** Set the {link LayoutManager} that this RecyclerV…

java网络编程 BufferedReader的readLine方法读不到数据且一直阻塞

最近在整理Java IO相关内容,会遇到一些以前没有注意的问题,特此记录,以供自查和交流。 需求: 基于Java的BIO API,实现简单的客户端和服务端通信模型,客户端使用BufferedReader的readLine方法读取System.i…

7、docker 集群

docker集群 1、docker file参数设置 2、docker composeCompose和Docker兼容性常用参数Docker-compose.yml配置文件Docker-compose命令大全compose常用调试命令compose文件格式示例应用python flask-rediscpu和gpu配置 附件参考: 1、docker file 参考:ht…

ASPICE 追溯性实践分享

01前言 接着之前的分享,遗留的追溯性ASPICE 认证实践及个人理解分享-CSDN博客文章浏览阅读961次,点赞22次,收藏17次。ASPICE是Automotive 和SPICE的组合,全英文为(Automotive Software ProcessImprovement and Determ…

树的遍历算法题总结(第二十六天)

144. 二叉树的前序遍历 题目 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 答案 class Solution {List<Integer> res new ArrayList(); public List<Integer> preorderTraversal(TreeNode root) {deal(root);return res;}void deal(TreeN…

C++修炼之路之继承<二>

目录 一&#xff1a;子类的六大默认成员函数 二&#xff1a;继承与友元 三&#xff1a;继承与静态成员 四&#xff1a;复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承&#xff1b;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…