Spring《三》DI 依赖注入

news/2024/4/24 23:02:19/
🍎道阻且长,行则将至。🍓

上一篇:Spring《二》bean 的实例化与生命周期
下一篇:敬请期待

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述


目录

  • 一、setter 注入🍉
    • 1.注入引用数据类型
    • 2.注入简单数据类型
  • 二、构造器注入🍊
    • 1.注入引用数据类型
    • 2.简单数据类型
  • 三、自动配置🍇
    • 1.自动装配方式
    • 2.自动装配的配置
        • 2.1 按类型注入
        • 2.2 按名称注入
    • 3.集合类型注入


向一个类中传递数据的方式有:普通方法(set 方法)构造方法。Spring 就相对应地为我们提供了两种注入方式:setter 注入构造器注入。同时也包括简单类型和引用类型(对象)注入。

*setter 方法构造器
引用类型类中添加 setter 方法,配置文件使用 property,ref = 引用对象类中添加构造器方法,配置文件使用 constructor-arg,ref = 引用对象
基本类型类中添加 setter 方法,配置文件使用 property,value = 值类中添加构造器方法,配置文件使用 constructor-arg,value = 值

一、setter 注入🍉

在 Spring 入门篇中进行的 DI 依赖注入就是setter方法。

我们先创建好 Maven 项目,和上一篇类似,添加好项目依赖,添加 Spring 配置文件。在项目中添加 BookDao、BookDaoImpl、UserDao、UserDaoImpl、BookService 和 BookServiceImpl 类以及 AppForDISet 运行类。

public class AppForDISet {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("mySpringSetFile.xml");BookService bookService = (BookService) ctx.getBean("bookService");bookService.save();}
}

1.注入引用数据类型

bookServiceImpl 对象中注入 bookDao userDao

  1. 在 BookServiceImpl 中声明属性并提供 setter 方法,同时在 save 方法中调用他们俩的 save
public class BookServiceImpl implements BookService{private BookDao bookDao;private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}public void save() {System.out.println("book service save ...");bookDao.save();userDao.save();}
}
  1. 在配置文件中使用 property 进行注入配置
<bean id="bookService"class="Demo.Srevice.impl.BookServiceimpl"><property name="bookDao" ref="bookDao"/><property name="userDao" ref="userDao"/>
</bean>
  1. 运行,注入成功
    在这里插入图片描述

2.注入简单数据类型

BookDaoImpl 注入一些简单数据类型的数据。

  1. 声明属性并提供 setter 方法
private String databaseName;
private int connectionNum;
public void setDatabaseName(String databaseName) {this.databaseName = databaseName;
}
public void setConnectionNum(int connectionNum) {this.connectionNum = connectionNum;
}
  1. 在配置文件中使用 property 注入
<bean id="bookDao" class="Demo.Srevice.impl.BookServiceimpl"><property name="databaseName" value="mysql"/><property name="connectionNum" value="10"/>
</bean>
  1. 修改一下这个类的 save 方法:System.out.println("Book dao save ..."+databaseName+":"+connectionNum);
  2. 运行,注入成功:
    在这里插入图片描述

二、构造器注入🍊

构造方法注入

可以继续使用前面的案例,将前面的注入删除或者注释掉。

1.注入引用数据类型

BookServiceImpl 类中的 bookDao userDao 修改成使用构造器的方式注入。使用快捷键 alt + insert 吧:
在这里插入图片描述
在这里插入图片描述

public BookServiceimpl(BookDao bookdao, UserDao userDao) {this.bookdao = bookdao;this.userDao = userDao;
}

在 Spring 配置文件里配置构造方式注入

    <bean id="bookService" class="Demo.Srevice.impl.BookServiceimpl">
<!--        <property name="bookdao" ref="bookDao"/>-->
<!--        <property name="userDao" ref="userDao"/>--><constructor-arg name="bookdao" ref="bookDao"/><constructor-arg name="userDao" ref="userDao"/></bean>

注入成功:
在这里插入图片描述

注意这种方法在构造器和配置文件中的参数顺序不能乱,交换两个参数前后位置会提示警告:
在这里插入图片描述

    <bean id="bookService" class="Demo.Srevice.impl.BookServiceimpl">
<!--        <property name="bookdao" ref="bookDao"/>-->
<!--        <property name="userDao" ref="userDao"/>--><constructor-arg name="userDao" ref="userDao"/><constructor-arg name="bookdao" ref="bookDao"/></bean>

在这里插入图片描述

Error creating bean with name ‘bookService’ defined in class path resource [mySpringSetFile.xml]: Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [Demo.Dao.impl.UserDaoimpl] to required type [Demo.Dao.BookDao]: Failed to convert value of type ‘Demo.Dao.impl.UserDaoimpl’ to required type ‘Demo.Dao.BookDao’; nested exception is java.lang.IllegalStateException: Cannot convert value of type ‘Demo.Dao.impl.UserDaoimpl’ to required type ‘Demo.Dao.BookDao’: no matching editors or conversion strategy found

2.简单数据类型

修改 BookDaoImpl 类,添加构造方法:

public BookDaoImpl(String databaseName, int connectionNum) {this.databaseName = databaseName;this.connectionNum = connectionNum;
}

修改配置文件:

<bean id="bookDao" class="Demo.Dao.impl.BookDaoimpl"><constructor-arg name="databaseName" value="mysql"/><constructor-arg name="connectionNum" value="666"/>
<!--        <property name="databaseName" value="mysql"/>-->
<!--        <property name="connectionNum" value="10"/>-->
</bean>

构造函数中方法的参数名发生变化后,配置文件中的 name 属性也需要跟着变,为了避免这种情况,可以选择 type 或者 index:
在这里插入图片描述

根据数据类型:

<bean id="bookDao" class="Demo.Dao.impl.BookDaoimpl"><constructor-arg type="int" value="10"/><constructor-arg type="java.lang.String" value="mysql"/>
<!--        <property name="databaseName" value="mysql"/>-->
<!--        <property name="connectionNum" value="10"/>-->
</bean>

根据参数位置:

<bean id="bookDao" class="Demo.Dao.impl.BookDaoimpl"><constructor-arg index="0" value="mysql"/><constructor-arg index="1" value="10"/>
<!--        <property name="databaseName" value="mysql"/>-->
<!--        <property name="connectionNum" value="10"/>-->
</bean>

运行注入成功:
在这里插入图片描述

同样的对于使用 name 的方法不能交换参数位置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
错误的把配置文件中第一个参数给了构造器第一个参数。

三、自动配置🍇

前面的 Spring 注入方法仍然很麻烦,Spring 提供了自动配置方法。就是 IOC 容器根据 bean 所依赖的资源在容器中自动查找并注入到 bean 中。用于引用类型依赖注入,不能对简单类型进行操作

1.自动装配方式

1.按类型(常用) byType
2.按名称 byName
3.按构造方法 constructor
4.不启用自动装配 no
在这里插入图片描述

2.自动装配的配置

再次把前面案例的注入删除。在 <bean> 中添加 autowire 属性。

2.1 按类型注入

<bean id="bookService" class="Demo.Srevice.impl.BookServiceimpl" autowire="byType"/>

1.需要注入属性的类中对应属性的 setter 方法不能省略。
2.被注入的对象必须要被 Spring 的 IOC 容器管理。
3.按照类型在 Spring 的 IOC 容器中如果找到多个对象,会报 NoUniqueBeanDefinitionException

2.2 按名称注入

如果一个类型在 IOC 中有多个对象,这个时候就需要按照名称注入(变量名与配置耦合,不推荐使用):

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>

按照名称去找对应的 bean 对象,找不到则注入 Null。
自动装配优先级低于 setter 注入与构造器注入,同时出现时自动装配配置失效。

3.集合类型注入

bean 中使用 property,根据集合类型:数组、List、Set、Map、Properties 设置 name 参数。
3.1 注入数组类型数据

<property name="array"><array><value>100</value><value>200</value><value>300</value></array>
</property>

3.2 注入 List 类型数据

<property name="list"><list><value>itcast</value><value>itheima</value><value>boxuegu</value><value>chuanzhihui</value></list>
</property>

List 的底层也是通过数组实现的,所以 <list><array> 标签是可以混用。

3.3 注入 Set 类型数据

<property name="set"><set><value>itcast</value><value>itheima</value><value>boxuegu</value><value>boxuegu</value></set>
</property>

3.4 注入 Map 类型数据

<property name="map"><map><entry key="country" value="china"/><entry key="province" value="henan"/><entry key="city" value="kaifeng"/></map>
</property>

3.5 注入 Properties 类型数据

<property name="properties"><props><prop key="country">china</prop><prop key="province">henan</prop><prop key="city">kaifeng</prop></props>
</property>

3.6 property 标签表示 setter 方式注入,构造方式注入 constructor-arg 标签内部也可以写 <array><list><set><map><props> 标签。
集合中要添加引用类型,只需要把 <value> 标签改成 <ref> 标签。


☕物有本末,事有终始,知所先后。🍭

🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓


http://www.ppmy.cn/news/46908.html

相关文章

Java基础(十七):日期时间API

Java基础系列文章 Java基础(一)&#xff1a;语言概述 Java基础(二)&#xff1a;原码、反码、补码及进制之间的运算 Java基础(三)&#xff1a;数据类型与进制 Java基础(四)&#xff1a;逻辑运算符和位运算符 Java基础(五)&#xff1a;流程控制语句 Java基础(六)&#xff1…

Golang流媒体实战之七:hls拉流服务源码阅读

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《Golang流媒体实战》系列的第七篇&#xff0c;继续学习一个重要且通用的知识点&#xff1a;hls拉流在《体验开源项目lal》一文中&#xff0…

【大数据基础】基于 TMDB 数据集的电影数据分析

https://dblab.xmu.edu.cn/blog/2400/ 实验内容 环境搭建 pip3 install bottle数据预处理 本次项目使用的数据集来自知名数据网站 Kaggle 的 tmdb-movie-metadata 电影数据集&#xff0c;该数据集包含大约 5000 部电影的相关数据。本次实验使用数据集中有关电影的数据表 tm…

公司新来一00后说我不会自动化测试,3个问题直接给他问趴下...

今天我们公司刚入职一小伙&#xff0c;听说是00后&#xff0c;今天在办公室交流了一下&#xff0c;他问我会不会自动化测试&#xff0c;我直呼好家伙&#xff0c;直接问了他3个开展自动化测试问题....一问3不知.....还有待加强呀 我们在制定自动化测试实施策略时&#xff0c;首…

哪个洗脱一体机好用?好用的洗拖一体机推荐

洗地机是一款使用非常方便的清洁工具&#xff0c;通常可以实现吸、拖、洗三个功能&#xff0c;对于各类家庭污渍都有着不错的处理能力&#xff0c;无论是干燥垃圾还是潮湿垃圾一律可以有效清理。不过很多新手朋友在选购洗地机时会因为看不懂参数而频繁踩雷。本文为大家整理了洗…

【hello Linux】理解文件系统

目录 创建文件的过程&#xff1a; 删除文件的过程&#xff1a; 创建目录的过程&#xff1a; 查看inode编号&#xff1a; 硬链接 软链接 Linux&#x1f337; 我们知道文件所有数据 文件内容 文件属性信息&#xff1b; 未打开的文件是被存放到磁盘/固态硬盘中的&#xff1b; …

Allegro thermal relief热风焊盘

为了画个通孔焊盘&#xff0c;看了很久的 Thermal relief相关的内容&#xff0c;终于基本上理解了。记录一下。 这篇文章讲得非常清楚&#xff1a; 深入理解Allegro之Thermal Relief与Anti Pad - 百度文库 (baidu.com) 热风焊盘般用在内层&#xff0c;减少一些焊盘和铜皮的连…

Leetcode究极刷题笔记(31~35)

&#xff08;31&#xff09;下一个排列&#xff08;中等&#xff09; 实现思路&#xff1a; 从题目中&#xff0c;我们可以看出本题的意思就是让你选一个比当前序列大的最小的那个解&#xff0c;比如132&#xff0c;哪么比它大的最小解就是213&#xff08;先从第一位开始比&am…

Js实现滚动变色的文字效果

<html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>滚动变色的文字js特效</title> </head> <body> <div style"width:736px;"> 请注意下方的文…

环境变量详解

目录 环境变量是什么&#xff1f; 常见环境变量 查看环境变量 指令查看 代码查看 系统调用查看 本地变量 环境变量全局性 环境变量是什么&#xff1f; 我们要执行一个我们所写的c/c程序时&#xff0c;需要./可执行文件&#xff0c;告诉操作系统你在哪里&#xff0c…

魔兽世界私服架设教程—魔兽大服务器合并列表

都说魔兽世界是最经典的网游&#xff0c;可惜我沉迷于程序的世界&#xff0c; 用以下命令down源码 git clone git://github.com/mangos/mangos.git 编译的时候会出错&#xff0c;找不到以下两个文件 revision.h SystemConfig.h 其实以上文件只是简单的定义同个编译的宏而…

数据库网络编程

数据库网络编程是一个重要的领域&#xff0c;它涉及到如何使用编程语言与数据库进行交互&#xff0c;以及如何设计和实现网络应用程序。在这篇文章中&#xff0c;我将探讨数据库网络编程的基础知识、常用技术和实践经验&#xff0c;以及一些应用案例和未来发展趋势。 一、基础…

PEIS源码,体检管理系统源码,C#医院体检系统源码

PEIS体检管理系统源码&#xff0c;医院体检系统源码PEIS源码&#xff0c;商业级源码&#xff0c;有演示。 PEIS医院体检管理系统采用C/S结构&#xff0c;前台开发工具为Vs2012&#xff0c;后台数据库采用oracle大型数据库。核心功能有&#xff1a;体检档案的录入、体检报告的输…

Web 开发会话技术之 -Cookie介绍以及源码分析和图分析以及Cookie的生命周期--路径--中文乱码的分析和代码示例

目录 Web 开发会话技术之 -Cookie 会话 基本介绍 1. 什么是会话&#xff1f; 2. 会话过程中要解决的一些问题&#xff1f; cookie 技术 cookie 介绍 二说 cookie cookie 可以用来做啥 cookie 基本使用 cookie 常用方法 cookie 底层实现机制-创建和读取 Cookie Crea…

【hello C++】内存管理

目录 前言&#xff1a; 1. C/C内存分布 2. C语言动态内存管理方式 3. C内存管理方式 3.1 new / delete 操作内置类型 3.2 new和delete操作自定义类型 4. operator new与operator delete函数 4.1 operator new与operator delete函数 5. new和delete的实现原理 5.1 内置类型 5.2…

顺序表的实现

思维导图&#xff1a; 一&#xff0c;顺序表 一&#xff0c;顺序表的创建&#xff08;位置&#xff1a;头文件内&#xff09; 1.1顺序表的结构体类型 要求&#xff1a;创建顺序表并使这个顺序表能够存放数据&#xff0c;能记录有效数据的个数&#xff0c;能够记录容量大小。…

python3 DataFrame一些好玩且高效的操作

pandas在处理Excel/DBs中读取出来&#xff0c;处理为DataFrame格式的数据时&#xff0c;处理方式和性能上有很大差异&#xff0c;下面是一些高效&#xff0c;方便处理数据的方法。 map/apply/applymaptransformagg遍历求和/求平均shift/diff透视表切片&#xff0c;索引&#x…

查询数据库空间(mysql和oracle)

Mysql版 1、查看所有数据库容量大小 -- 查看所有数据库容量大小 SELECTtable_schema AS 数据库,sum( table_rows ) AS 记录数,sum(TRUNCATE ( data_length / 1024 / 1024, 2 )) AS 数据容量(MB),sum(TRUNCATE ( index_length / 1024 / 1024, 2 )) AS 索引容量(MB) FROMinfor…

如何识别来自 ChatGPT 的文本输出

既然 ChatGPT 生成的内容需要和人类生成的内容有明确的区分&#xff0c;那如果我们拿到一个几经转手的、缺失标记的内容片段&#xff0c;有没有办法来判断他的作者&#xff0c;到底属于 ChatGPT&#xff0c;还是属于人类呢&#xff1f; openai 公司&#xff0c;为此主动推出了…

python中__init__.py文件

例子 不要使用相对路径。 __init__.py# from net.functions import * VERSION "1.0.0"import os, sys module_path os.path.dirname(__file__) module_parent_path os.path.dirname(module_path) sys.path.extend([module_path, module_parent_path]) from net i…