一、DI介绍

1、DI介绍

  • 依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入。
  • Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为“依赖注入”的方式来管理Bean之间的依赖关系。
  • 使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用。依赖注入是一种优秀的解耦方式,其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。

2、依赖注入

依赖注入: Dependency Injection。它是 spring 框架核心 ioc 的具体实现。

3、为什要依赖注入

直接用对象,不需要去new对象。所谓的注入就是创建对象的过程而已。

  • 传统的代码,每个对象负责管理与自己需要依赖的对象,导致如果需要切换依赖对象的实现类时,需要修改多处地方。同时,过度耦合也使得对象难以进行单元测试。

  • 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制。

  • 例如:我们控制层调用业务层需要在控制层创建业务层的对象,之前我们需要Person p = new Person;现在不需要我们自己去new person,直接交给spring去创建,我可以直接拿过来用。

Spring 支持的注入方式共有四种: set 注入、构造器注入、静态工厂注入、实例化工厂注入。

4、IOC与DI之间的关系

IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。

DI(Dependence Injection 依赖注入):将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)。

  • 控制反转是一种思想
  • 依赖注入是一种设计模式
  • IoC框架使用依赖注入作为实现控制反转的方式

说人话:就是DI与IOC相辅相成,相互包含。不能说成DI就是IOC,这两个本质区别是:IOC是思想,DI设计模式。

二、Spring的依赖注入方式

1、Set注入

1、set注入介绍

思考:调用某个类的方法,你是怎么操作的?

答:我通过该类的构造器创建对象,通过对象去调用方法。

看图说话:

方式一与方式二对比:

  • 方式二没有主动的去实例对象,而是通过带参数的方法传递过来UserDao对象,从而实现UserService对UserDao的依赖.

  实际上创建对象是交给Spring容器来创建的

  • 属性字段需要提供set方法。并且还需要通过修改spring的配置文件,进行相关的注入信息配置。

2、Set注入标签介绍

名称:property

类型:标签

归属:bean标签

作用:使用set方法的形式为bean提供资源

格式:
<bean>
<property />
</bean>
基本属性: <property name="propertyName" value="propertyValue" ref="beanId"/>
name:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称) value:设定非引用类型属性对应的值,不能与ref同时使用 ref:设定引用类型属性对应bean的id ,不能与value同时使用 注意:一个bean可以有多个property标签,属性字段需要提供set方法

3、测试Set注入方式创建对象

  1. 在UserServiceImpl创建UserDao的变量,并在UserServiceImpl变量提供Set方法。
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao){

        this.userDao = userDao;

    }

    @Override
public void saveUser() {
System.out.println("service层通过注入的方式调用dao层,成功啦!");
userDao.saveUser();
}
  1. 接口类UserService
public interface UserService {
void saveUser();
}
  1. dao层方法
public class UserDao {

    public void saveUser(){
System.out.println("我是dao层");
}
}

4.配置文件配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--
<property/> 中的name对应set方法的set后面的名字且首字母小写
ref 代表注入的是引用类型,所以需要填入药注入bean的id
说明:service引用到层,相当于在service里面创建userDao的对象,直接被service引用,与new对象调用方法类似
-->
<property name="userDao" ref="userDao"/>
</bean> <!--将注入的资源声明为bean,交由spring管理-->
<bean id="userDao" class="com.why.dao.UserDao"/>
</beans>
  1. 测试类
public class UserController {
public static void main(String[] args) { //获取Spring上下文环境 (加载配置文件)
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); /*
通过getBean方法得到Spring容器中实例化好的Bean对象 (实例化Bean对象)
userService代表的是配置文件中bean标签的id属性值(id标识唯一的bean)
*/
UserService userService = (UserService) context.getBean("userService");
userService.saveUser();
}
}

6.测试结果

程序没有报错,并正确输出我们要打印的东西

2、构造方法注入

1、构造器注入标签介绍

名称:constructor-arg

类型:标签

归属:bean标签

作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作

格式:
<bean>
<constructor-arg />
</bean> 基本属性:
<constructor-arg name="argsName" value="argsValue /> name:对应bean中的构造方法所携带的参数名
value:设定非引用类型构造方法参数对应的值,不能与ref同时使用 其他属性: <constructor-arg index="arg-index" type="arg-type" ref="beanId"/> ref:设定引用类型构造方法参数对应bean的id ,不能与value同时使用 type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验 index :设定构造方法参数的位置,用于按位置匹配参数,参数index值从0开始计数 注意:一个bean可以有多个constructor-arg标签

2、构造注入测试案例

  1. 在UserServiceImpl创建UserDao的变量,并在UserServiceImpl变量提供构造方法。
public class UserServiceImpl implements UserService {

    private UserDao userDao;
private String name;
private int age; //根据构造器进行注入
public UserServiceImpl(UserDao userDao, String name, int age) {
this.userDao = userDao;
this.name = name;
this.age = age;
} @Override
public void saveUser() {
System.out.println("name="+name);
System.out.println("age="+age);
userDao.saveUser();
} public void destroy(){
System.out.println("bean销毁");
}
}
  1. 修改配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--
构造器注入
-->
<bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--
对构造器进行赋值
-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="name" value="laity"/> </bean> <bean id="userDao" class="com.why.dao.UserDao"></bean>
</beans>

3. 其它代码与set注入代码相同

  1. 测试结果

  1. 构造标签的属性
//根据构造器进行注入
public UserServiceImpl(UserDao userDao, String name, int age) {
this.userDao = userDao;
this.name = name;
this.age = age;
}

带name属性

<bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--
对构造器进行赋值
-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="name" value="laity"/> </bean>

不带name属性,顺序要按照构造方法的参数类型进行设置

<bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--
对构造器进行赋值
-->
<constructor-arg ref="userDao"></constructor-arg>
<constructor-arg value="22"></constructor-arg>
<constructor-arg value="laity"/> </bean>

index0表示第一个参数,index1表示第二个参数,以此类推

<bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--
对构造器进行赋值
-->
<constructor-arg index ="0" ref="userDao"></constructor-arg>
<constructor-arg index ="1" value="22"></constructor-arg>
<constructor-arg index ="2" value="laity"/>
</bean>

3、集合注入

1、集合类型标签介绍

名称:array,list,set,map,props

类型:标签

归属:property标签 或 constructor-arg标签

作用:注入集合数据类型属性

格式:
<property>
<list></list>
</property>

1、集合类型数据注入——list(重点)

<property name="xxx">
<list>
<value>why</value>
<value>66666</value>
</list>
</property>

(2)集合类型数据注入——props(重点)

<property name="xxx">
<props>
<prop key="name">javaxxf</prop>
<prop key="value">666666</prop>
</props>
</property>

(3)集合类型数据注入——array (了解)

<property name="xxx">
<array>
<value>123456</value>
<value>66666</value>
</array>
</property>

(4)集合类型数据注入——set(了解)

<property name="xxx">
<set>
<value>javaxxf</value>
<value>66666</value>
</set>
</property>

(5)集合类型数据注入——map(了解)

<property name="xxx">
<map>
<entry key="name" value="javaxf66666"/>
<entry key="value" value="66666"/>
</map>
</property><property name="xxx">
<map>
<entry key="name" value="javaxf66666"/>
<entry key="value" value="66666"/>
</map>
</property>

2、测试集合注入

  1. 创建集合并提供set方法
package com.why.service.impl;

import com.why.service.UserService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties; public class UserServiceImpl implements UserService { private ArrayList arrayList;
private Properties properties;
private int[] arr;
private HashSet hset;
private HashMap hmap; public void setArrayList(ArrayList arrayList) {
this.arrayList = arrayList;
} public void setProperties(Properties properties) {
this.properties = properties;
} public void setArr(int[] arr) {
this.arr = arr;
} public void setHset(HashSet hset) {
this.hset = hset;
} public void setHmap(HashMap hmap) {
this.hmap = hmap;
} @Override
public void saveUser() {
System.out.println("ArrayList"+arrayList);
System.out.println("Properties"+properties);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("HashSet"+hset);
System.out.println("HashMap"+hmap);
}
}
  1. 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.why.service.impl.UserServiceImpl">
<!--list集合配置-->
<property name="arrayList">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<!--properties配置-->
<property name="properties">
<props>
<prop key="properties1">java</prop>
<prop key="properties2">java</prop>
<prop key="properties3">java</prop>
</props>
</property>
<!--数组配置-->
<property name="arr">
<array>
<value>11</value>
<value>12</value>
<value>13</value>
</array>
</property>
<!--hashmap集合配置-->
<property name="hmap">
<map>
<entry key="map1" value="Laity1"></entry>
<entry key="map2" value="Laity2"></entry>
</map>
</property>
<!--hashset集合配置-->
<property name="hset">
<set>
<value>hset1</value>
<value>hset2</value>
<value>hset3</value>
</set>
</property>
</bean> </beans>
  1. 运行结果

三、参考资料

理解Spring中的IoC和DI

控制反转(IoC)与依赖注入(DI)

3、Spring的DI依赖注入的更多相关文章

  1. Spring:DI依赖注入的几种方式

    据我所学,spring实现依赖注入(DI)的方式分为三大类:基于构造器(构造方法)的依赖注入.基于setter的依赖注入.其他方式(c命名空间.p命名空间等).其中推荐使用setter方法注入,这种注 ...

  2. Spring学习——DI(依赖注入)

    IOC容器,处理对象依赖关系 IOC与DI: IOC :是一个容器,创建对象的容器 DI :在容器创建对象后,处理对象的依赖关系,也叫依赖注入! 方式1:通过set方法注入值 可以给普通属性.集合属性 ...

  3. 初识Spring框架实现IOC和DI(依赖注入)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的, IoC是 ...

  4. Spring详解(三)------DI依赖注入

    上一篇博客我们主要讲解了IOC控制反转,也就是说IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建.初始化.销毁等工作交给spring容器来做.那么创建对象的时候,有可 ...

  5. Spring:(二)DI依赖注入方式

    DI 依赖注入 DI(Dependency Injection)依赖注入,说简单一点就将类里面的属性在创建类的过程中给属性赋值,即将对象依赖属性(简单值,集合,对象)通过配置设值给该对象. 属性注入的 ...

  6. 一) Spring 介绍、IOC控制反转思想与DI依赖注入

    一.spring介绍1.IOC反转控制思想(Inversion of Control)与DI依赖注入(Dependency Injection)2.AOP面向切面的编程思想与动态代理3.作用:项目的粘 ...

  7. Spring-初识Spring框架-IOC控制反转(DI依赖注入)

    ---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...

  8. Spring的三大核心思想:IOC(控制反转),DI(依赖注入),AOP(面向切面编程)

    Spring核心思想,IoC与DI详解(如果还不明白,放弃java吧) 1.IoC是什么?    IoC(Inversion of Control)控制反转,IoC是一种新的Java编程模式,目前很多 ...

  9. 三大框架 之 Spring(IOC控制反转、DI依赖注入)

    目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...

随机推荐

  1. CentOS 8.4安装Docker

    前言: Docker 是一个用于开发.传送和运行应用程序的开放平台.Docker 使您能够将应用程序与基础设施分开,以便您可以快速交付软件.使用 Docker,您可以像管理应用程序一样管理基础设施.通 ...

  2. Centos8 Docker部署 .Net6 项目

    .Net6项目发布 1.在VS中发布项目,并编写好Dockerfile文件 Dockerfile文件内容如下: FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS ...

  3. 探究 Go 源码中 panic & recover 有哪些坑?

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客: https://www.luozhiyun.com/archives/627 本文使用的go的源码1.17.3 前言 写这一篇文章的原因是 ...

  4. Spark-StructuredStreaming 下的checkpointLocation分析以及对接 Grafana 监控和提交Kafka Lag 监控

    一.Spark-StructuredStreaming checkpointLocation 介绍 Structured Streaming 在 Spark 2.0 版本于 2016 年引入, 是基于 ...

  5. 关于阿里云图标的使用 iconfont

    iconfont 关于阿里云图标库使用的介绍 对于添加到网页中的iconfont可使用以下几种方式: 首先需要进入阿里云图标库官网进行对应的下载iconfont-阿里巴巴矢量图标库 将需要的图标加入到 ...

  6. Java设计模式之(十三)——模板方法模式

    1.什么是模板模式? Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. ...

  7. 2017年最有前景的十大IT职业岗位

    在IT行业,并不常存在失业的现象,因为目前整个行业存在严重的专业人才供给不足的现象:但同样,想要进入这个行业并牢牢站稳脚跟,你也需要拥有更强于其他行业的竞争力和承受更大的压力.那在行业中,哪些职位更有 ...

  8. Codeforces 708E - Student's Camp(前缀和优化 dp)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙 *3100,%%% 首先容易注意到 \(\forall i\in[1,m]\),第 \(i\) 行剩余的砖块一定构成一个区间,设其为 ...

  9. 用pipenv管理python虚拟环境

    python的虚拟环境可以为项目创建一个独立的环境,能够解决使用不同版本依赖给项目带来冲突的麻烦.创建虚拟环境的方式有很多种,pipenv会自动帮你管理虚拟环境和依赖文件,并且提供了一系列命令和选项来 ...

  10. DTOJ 4027:挖煤

    挖煤 [问题描述]众所周知, 小C是挖煤好手.今天他带着他的魔法镐子去挖煤 ,他的镐子一开始有$w$点魔力.他的挖煤 路线 上会依次 经过$n$个地点, 地点, 每个 地点是煤矿或者补给站,设小C当前 ...