我们先来思考

  • 向一个类中传递数据的方式有几种?

    • 普通方法(set 方法)
    • 构造方法
  • 依赖注入描述了在容器中建立 bean 与 bean 之间的依赖关系的过程,如果 bean 运行需要的是数字或字符串呢?

    • 引用类型
    • 简单类型(基本数据类型与 String)

Spring 就是基于上面这些知识点,为我们提供了两种注入方式,分别是:

  • setter 注入

    • 简单类型
    • 引用类型
  • 构造器注入

    • 简单类型
    • 引用类型

1. setter 注入

  1. 对于 setter 方式注入引用类型的方式之前已经学习过,快速回顾下:
  • 在 bean 中定义引用类型属性,并提供可访问的set方法
  1. public class BookServiceImpl implements BookService {
  2.    private BookDao bookDao;
  3.    public void setBookDao(BookDao bookDao) {
  4.        this.bookDao = bookDao;
  5.   }
  6. }
  • 配置中使用​property 标签 ref​属性注入引用类型对象
  1. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  2. <property name="bookDao" ref="bookDao"/>
  3. </bean>
  4. <bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/>

1.1 注入引用数据类型

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
  6. <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
  7. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  8. <property name="bookDao" ref="bookDao"/>
  9. <property name="userDao" ref="userDao"/>
  10. </bean>
  11. </beans>

1.2 注入简单数据类型

思考:

引用类型使用的是<property name="" ref=""/>​,简单数据类型还是使用 ref 么?

ref 是指向 Spring 的 IOC 容器中的另一个 bean 对象的,对于简单数据类型,没有对应的 bean 对象,该如何配置?

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
  6. <property name="databaseName" value="mysql"/>
  7. <property name="connectionNum" value="10"/>
  8. </bean>
  9. <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
  10. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  11. <property name="bookDao" ref="bookDao"/>
  12. <property name="userDao" ref="userDao"/>
  13. </bean>
  14. </beans>

注意:两个 property 注入标签的顺序可以任意。

对于 setter 注入方式的基本使用就已经介绍完了,

  • 对于引用数据类型使用的是<property name="" ref=""/>
  • 对于简单数据类型使用的是<property name="" value=""/>

2. 构造器注入

2.1 构造器注入引用数据类型

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
  6. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  7. <constructor-arg name="bookDao" ref="bookDao"/>
  8. </bean>
  9. </beans>

说明:

标签

  • name 属性对应的值为构造函数中方法形参的参数名,必须要保持一致。
  • ref 属性指向的是 spring 的 IOC 容器中其他 bean 对象。

2.2 构造器注入多个引用数据类型

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
  6. <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
  7. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  8. <constructor-arg name="bookDao" ref="bookDao"/>
  9. <constructor-arg name="userDao" ref="userDao"/>
  10. </bean>
  11. </beans>

说明:这两个<contructor-arg>​ 的配置顺序可以任意

2.3 构造器注入多个简单数据类型

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
  6.        <constructor-arg name="databaseName" value="mysql"/>
  7.        <constructor-arg name="connectionNum" value="666"/>
  8.    </bean>
  9.    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
  10.    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
  11.        <constructor-arg name="bookDao" ref="bookDao"/>
  12.        <constructor-arg name="userDao" ref="userDao"/>
  13.    </bean>
  14. </beans>

说明:这两个<contructor-arg>​ 的配置顺序可以任意

上面已经完成了构造函数注入的基本使用,但是会存在一些问题:

  • 当构造函数中方法的参数名发生变化后,配置文件中的 name 属性也需要跟着变
  • 这两块存在紧耦合,具体该如何解决?

在解决这个问题之前,需要提前说明的是,这个参数名发生变化的情况并不多,所以上面的还是比较主流的配置方式,下面介绍的,大家都以了解为主。

方式一:删除 name 属性,添加 type 属性,按照类型注入

  1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
  2.    <constructor-arg type="int" value="10"/>
  3.    <constructor-arg type="java.lang.String" value="mysql"/>
  4. </bean>
  • 这种方式可以解决构造函数形参名发生变化带来的耦合问题
  • 但是如果构造方法参数中有类型相同的参数,这种方式就不太好实现了

方式二:删除 type 属性,添加 index 属性,按照索引下标注入,下标从 0 开始

  1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
  2.    <constructor-arg index="1" value="100"/>
  3.    <constructor-arg index="0" value="mysql"/>
  4. </bean>
  • 这种方式可以解决参数类型重复问题
  • 但是如果构造方法参数顺序发生变化后,这种方式又带来了耦合问题

介绍完两种参数的注入方式,具体我们该如何选择呢?

  1. 强制依赖使用构造器进行,使用 setter 注入有概率不进行注入导致 null 对象出现

    • 强制依赖指对象在创建的过程中必须要注入指定的参数
  2. 可选依赖使用 setter 注入进行,灵活性强

    • 可选依赖指对象在创建过程中注入的参数可有可无
  3. Spring 框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨

  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用 setter 注入完成可选依赖的注入

  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供 setter 方法就必须使用构造器注入

  6. 自己开发的模块推荐使用 setter 注入

3. 关于 setter 注入和构造器注入的小结

  • setter 注入

    • 简单数据类型

      1. <bean ...>
      2. <property name="" value=""/>
      3. </bean>
    • 引用数据类型

      1. <bean ...>
      2. <property name="" ref=""/>
      3. </bean>
  • 构造器注入

    • 简单数据类型

      1. <bean ...>
      2. <constructor-arg name="" index="" type="" value=""/>
      3. </bean>
    • 引用数据类型

      1. <bean ...>
      2. <constructor-arg name="" index="" type="" ref=""/>
      3. </bean>
  • 依赖注入的方式选择上

    • 建议使用 setter 注入
    • 第三方技术根据情况选择

4. 自动装配

前面花了大量的时间把 Spring 的注入去学习了下,总结起来就一个字麻烦。

问:麻烦在哪?

答:配置文件的编写配置上。

问:有更简单方式么?

答:有,自动配置

4.1 什么是依赖自动装配?

IoC 容器根据 bean 所依赖的资源在容器中自动查找并注入到 bean 中的过程称为自动装配

4.2 自动装配方式有哪些?

  • 按类型(常用)
  • 按名称
  • 按构造方法
  • 不启用自动装配

4.3 完成自动装配的配置

自动装配只需要修改 applicationContext.xml 配置文件即可:

(1)将<property>​ 标签删除

(2)在<bean>​ 标签中添加 autowire 属性

首先来实现按照类型注入的配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
  6.    <!--autowire属性:开启自动装配,通常使用按类型装配-->
  7.    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
  8. </beans>

注意事项:

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

一个类型在 IOC 中有多个对象,还想要注入成功,这个时候就需要按照名称注入,配置方式为:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
  6.    <!--autowire属性:开启自动装配,通常使用按类型装配-->
  7.    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>
  8. </beans>

注意事项:

  • 按照名称注入中的名称指的是什么?

    ​​​​

    • bookDao 是 private 修饰的,外部类无法直接方法

    • 外部类只能通过属性的 set 方法进行访问

    • 对外部类来说,setBookDao 方法名,去掉 set 后首字母小写是其属性名

      • 为什么是去掉 set 首字母小写?
      • 这个规则是 set 方法生成的默认规则,set 方法的生成是把属性名首字母大写前面加 set 形成的方法名
    • 所以按照名称注入,其实是和对应的 set 方法有关,但是如果按照标准起名称,属性名和 set 对应的名是一致的

  • 如果按照名称去找对应的 bean 对象,找不到则注入 Null

  • 当某一个类型在 IOC 容器中有多个对象,按照名称注入只找其指定名称对应的 bean 对象,不会报错

两种方式介绍完后,以后用的更多的是​按照类型​注入。

最后对于依赖注入,需要注意一些其他的配置特征:

  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  2. 使用按类型装配时(byType)必须保障容器中相同类型的 bean 唯一,推荐使用
  3. 使用按名称装配时(byName)必须保障容器中具有指定名称的 bean,因变量名与配置耦合,不推荐使用
  4. 自动装配优先级低于 setter 注入与构造器注入,同时出现时自动装配配置失效

5. 集合注入

常见的集合类型

  • 数组
  • List
  • Set
  • Map
  • Properties

5.1 注入数组类型数据

  1. <property name="array">
  2.    <array>
  3.        <value>100</value>
  4.        <value>200</value>
  5.        <value>300</value>
  6.    </array>
  7. </property>

5.2 注入 List 类型数据

  1. <property name="list">
  2.    <list>
  3.        <value>itcast</value>
  4.        <value>itheima</value>
  5.        <value>boxuegu</value>
  6.        <value>chuanzhihui</value>
  7.    </list>
  8. </property>

5.3 注入 Set 类型数据

  1. <property name="set">
  2.    <set>
  3.        <value>itcast</value>
  4.        <value>itheima</value>
  5.        <value>boxuegu</value>
  6.        <value>boxuegu</value>
  7.    </set>
  8. </property>

5.4 注入 Map 类型数据

  1. <property name="map">
  2.    <map>
  3.        <entry key="country" value="china"/>
  4.        <entry key="province" value="henan"/>
  5.        <entry key="city" value="kaifeng"/>
  6.    </map>
  7. </property>

5.5 注入 Properties 类型数据

  1. <property name="properties">
  2.    <props>
  3.        <prop key="country">china</prop>
  4.        <prop key="province">henan</prop>
  5.        <prop key="city">kaifeng</prop>
  6.    </props>
  7. </property>

说明:

  • property 标签表示 setter 方式注入,构造方式注入 constructor-arg 标签内部也可以写<array>​、<list>​、<set>​、<map>​、<props>​ 标签
  • List 的底层也是通过数组实现的,所以<list>​ 和<array>​ 标签是可以混用
  • 集合中要添加引用类型,只需要把<value>​ 标签改成<ref>​ 标签,这种方式用的比较少

4. DI相关内容的更多相关文章

  1. linux用户权限相关内容查看

    linux用户权限相关内容查看 1   用户信息 创建用户一个名为 webuser 的账号,并填写相应的信息: root@iZ94fabhqhuZ:~# adduser webuser Adding ...

  2. SharePoint安全 - 在Goolge和Bing中查找SharePoint相关内容

    博客地址 http://blog.csdn.net/foxdave 本篇提供两个查询串字典,分别对应Google和Bing的搜索,用来查询SharePoint网站的相关内容 Google ShareP ...

  3. 韩顺平细说Servlet视频系列之tom相关内容

    韩顺平细说Servlet视频系列之tom相关内容 tomcat部署项目操作(注意:6.0版本以后的支持该操作,5.x版本需要另外配置?待验证!) 项目发布到tomcat的webapps文件下,然后启动 ...

  4. jQuery实现页内查找相关内容

    当需要在页面中查找某个关键字时,一是可以通过浏览器的查找功能实现,二是可以通过前端脚本准确查找定位,本文介绍通过jQuery实现的页面内容查找定位的功能,并可扩展显示查找后的相关信息. 本文以查找车站 ...

  5. Struts2(四)——页面相关内容

    上篇博客总结了数据流转各个方面的内容,这篇重点说一下框架对于界面上知识. 一,说到页面,记得在总体介绍中,说到Struts2比Struts1的一方面优势就是它支持更多的视图技术(Freemarker, ...

  6. 学习笔记之html5相关内容

    写一下昨天学习的html5的相关内容,首先谈下初次接触html5的感受.以前总是听说html5是如何的强大,如何的将要改变世界.总是充满了神秘感.首先来谈一下我接触的第一个属性是  input的里面的 ...

  7. 基于KNN的相关内容推荐

    如果做网站的内容运营,相关内容推荐可以帮助用户更快地寻找和发现感兴趣的信息,从而提升网站内容浏览的流畅性,进而提升网站的价值转化.相关内容 推荐最常见的两块就是“关联推荐”和“相关内容推荐”,关联推荐 ...

  8. 第一天上午——HTML网页基础知识以及相关内容

    今天上午学习了HTML基础知识以及相关内容,还有DW的基本使用方法. HTML(HyperText Markup Language):超文本标记语言,超文本:网页中除了包含文本文字之外,还包含了图片, ...

  9. python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。

    本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...

  10. 在地图中调用显示FeatureLayer并进行render、popupTemplate、添加图例等相关内容的设置

    ArcGIS Server发布完FeatureLayer后,就可以在自己的代码中调用并在地图上显示出来了. 一.代码框架 调用FeatureLayer,要在require开头引入"esri/ ...

随机推荐

  1. [软件工程]TO B型IT软件企业在工程管理角度所存在的诸多问题

    组织架构与分工? 各子组织的职责.边界是否明确? (安装.升级)部署规范? 必须有部署文档. 各个模块/组件部署在哪台服务器?哪个路径下? 一切非正式启用的任务.文件(夹).安装资料必须依据实际用途以 ...

  2. [Linux]Xshell连接Centos7能Ping通但无法连接问题[ssh(d)+firewalld/iptables+chkconfig]

    一 方案与思路 0 xshell客户端监测是否能够ping通目标服务器. 前提:知晓目标服务器IP地址 Linux: ifconfig -a Windows: ipconfig -a 1 利用fire ...

  3. 基于SqlSugar的开发框架循序渐进介绍(25)-- 基于SignalR实现多端的消息通讯

    基于ASP.NET Core SignalR 可以实现客户端和服务器之间进行即时通信.本篇随笔介绍一些SignalR的基础知识,以及结合对SqlSugar的开发框架的支持,实现SignalR的多端处理 ...

  4. 在 Rainbond 上使用在线知识库系统zyplayer-doc

    zyplayer-doc 是一款适合企业和个人使用的WIKI知识库管理工具,提供在线化的知识库管理功能,专为私有化部署而设计,最大程度上保证企业或个人的数据安全,可以完全以内网的方式来部署使用它. 当 ...

  5. abp(net core)+easyui+efcore实现仓储管理系统——模块管理升级之上(六十一)

    Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  6. DeFi4-稳定币

    稳定币--稳定 是一个相对的度量指标 波动性,收益率标准差 在一个时间段内最大跌幅 Fiat,例如: 欧元.英镑的波动率为6-12% (波动本身并不能反映价格的范围 稳定币 vs 锚定币 稳定币类型 ...

  7. JVM调优笔记(一)--Nacos GC引发的服务批量下线问题

    故障背景 线上批量发服务下线的告警邮件,偶发nacos连接超时.采用了spring boot admin(以下称sba)进行服务监控. 原因分析 因为sba服务是基于nacos对其它服务进行监控,所以 ...

  8. 如何借助分布式存储 JuiceFS 加速 AI 模型训练

    传统的机器学习模型,数据集比较小,模型的算法也比较简单,使用单机存储,或者本地硬盘就足够了,像 JuiceFS 这样的分布式存储并不是必需品. 随着近几年深度学习的蓬勃发展,越来越多的团队开始遇到了单 ...

  9. Pillow + pytesseract + tesseract-ocr 破解简单的图形验证码

    前言: 我们在做WEB UI自动化测试时,会遇到一些图形验证码,今天就来简单介绍下,如何来识别简单的图形验证码. 一.安装 ◇ Pillow pip3 install Pillow ◇ pytesse ...

  10. 2022-04-18:things是一个N*3的二维数组,商品有N件,商品编号从1~N, 比如things[3] = [300, 2, 6], 代表第3号商品:价格300,重要度2,它是6号商品的附属

    2022-04-18:things是一个N3的二维数组,商品有N件,商品编号从1~N, 比如things[3] = [300, 2, 6], 代表第3号商品:价格300,重要度2,它是6号商品的附属商 ...