首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【Spring教程六】Spring框架DI相关内容大揭秘:全面深入理解DI(依赖注入)以及setter注入与构造器注入全面详解

  • 24-03-05 07:20
  • 4453
  • 11124
blog.csdn.net

目录

  • 1 setter注入
    • 1.1 环境准备
    • 1.2 注入引用数据类型
    • 1.3 注入简单数据类型
  • 2 构造器注入
    • 2.1 环境准备
    • 2.2 构造器注入引用数据类型
    • 2.3 构造器注入多个引用数据类型
    • 2.4 构造器注入多个简单数据类型
    • 2.5 解决紧耦合问题
  • 3 总结

欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 Bean的生命周期》。

在这里插入图片描述
前面我们已经完成了bean相关操作的讲解,接下来就进入第二个大的模块DI依赖注入,首先来介绍下
Spring中有哪些注入方式?
我们先来思考

  • 向一个类中传递数据的方式有几种?
    • 普通方法(set方法)
    • 构造方法
  • 依赖注入描述了在容器中建立bean与bean之间的依赖关系的过程,如果bean运行需要的是数字或字符串呢?
  • 引用类型
  • 简单类型(基本数据类型与String)

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

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

依赖注入的方式已经介绍完,接下来挨个学习下:

1 setter注入

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

1.1 环境准备

为了更好的学习下面内容,我们依旧准备一个新环境:

  • 创建一个Maven项目
  • pom.xml添加依赖
  • resources下添加spring的配置文件
    这些步骤和前面的都一致,大家可以快速的拷贝即可,最终项目的结构如下:
    在这里插入图片描述
    (1)项目中添加BookDao、BookDaoImpl、UserDao、UserDaoImpl、BookService和
    BookServiceImpl类
//BookDao.java
public interface BookDao {
 	public void save();
 }
//BookDaoImpl.java
public class BookDaoImpl implements BookDao {
	 public void save() {
	 	System.out.println("book dao save ...");
	 }
}
//UserDao.java
 public interface UserDao {
	public void save();
}
//UserDaoImpl.java
 public class UserDaoImpl implements UserDao {
	 public void save() {
	 	System.out.println("user dao save ...");
	 }
 }
//BookService.java
 public interface BookService {
 	public void save();
 }
//BookServiceImpl.java
 public class BookServiceImpl implements BookService{
	private BookDao bookDao;
	 public void setBookDao(BookDao bookDao) {
	 	this.bookDao = bookDao;
	 }

	 public void save() {
		 System.out.println("book service save ...");
		 bookDao.save();
	 }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

(2)resources下提供spring的配置文件


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<property name="bookDao" ref="bookDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(3)编写AppForDISet运行类,加载Spring的IOC容器,并从中获取对应的bean对象

public class AppForDISet {
	public static void main( String[] args ) {
		ApplicationContext ctx = new
		ClassPathXmlApplicationContext("applicationContext.xml");
		BookService bookService = (BookService) ctx.getBean("bookService");
		bookService.save();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接下来,在上面这个环境中来完成setter注入的学习:

1.2 注入引用数据类型

需求:在bookServiceImpl对象中注入userDao
1.在BookServiceImpl中声明userDao属性
2.为userDao属性提供setter方法
3.在配置文件中使用property标签注入

步骤1:声明属性并提供setter方法
在BookServiceImpl中声明userDao属性,并提供setter方法

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

步骤2:配置文件中进行注入配置
在applicationContext.xml配置文件中使用property标签注入

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
	<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<property name="bookDao" ref="bookDao"/>
		<property name="userDao" ref="userDao"/>
	</bean>
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

步骤3:运行程序
运行AppForDISet类,查看结果,说明userDao已经成功注入。
在这里插入图片描述

1.3 注入简单数据类型

需求:给BookDaoImpl注入一些简单数据类型的数据
参考引用数据类型的注入,我们可以推出具体的步骤为:
1.在BookDaoImpl类中声明对应的简单数据类型的属性
2.为这些属性提供对应的setter方法
3.在applicationContext.xml中配置

思考:
引用类型使用的是 ,简单数据类型还是使用ref么?
ref是指向Spring的IOC容器中的另一个bean对象的,对于简单数据类型,没有对应的bean对象,该如何配置?
步骤1:声明属性并提供setter方法
在BookDaoImpl类中声明对应的简单数据类型的属性,并提供对应的setter方法

public class BookDaoImpl implements BookDao {
	private String databaseName;
	private int connectionNum;
	public void setConnectionNum(int connectionNum) {
		this.connectionNum = connectionNum;
	}
	public void setDatabaseName(String databaseName) {
		this.databaseName = databaseName;
	}
	public void save() {
		System.out.println("book dao save..."+databaseName+","+connectionNum);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

步骤2:配置文件中进行注入配置
在applicationContext.xml配置文件中使用property标签注入


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
		<property name="databaseName" value="mysql"/>
		<property name="connectionNum" value="10"/>
	bean>
	<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<property name="bookDao" ref="bookDao"/>
		<property name="userDao" ref="userDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

说明:
value:后面跟的是简单数据类型,对于参数类型,Spring在注入的时候会自动转换,但是不能写成

<property name="connectionNum" value="abc"/>
  • 1

这样的话,spring在将abc转换成int类型的时候就会报错。
步骤3:运行程序
运行AppForDISet类,查看结果,说明userDao已经成功注入。
在这里插入图片描述
注意:两个property注入标签的顺序可以任意。
对于setter注入方式的基本使用就已经介绍完了,

  • 对于引用数据类型使用的是
  • 对于简单数据类型使用的是

2 构造器注入

2.1 环境准备

构造器注入也就是构造方法注入,学习之前,还是先准备下环境:

  • 创建一个Maven项目
  • pom.xml添加依赖
  • resources下添加spring的配置文件
    这些步骤和前面的都一致,大家可以快速的拷贝即可,最终项目的结构如下:
    在这里插入图片描述
    (1)项目中添加BookDao、BookDaoImpl、UserDao、UserDaoImpl、BookService和BookServiceImpl类
public interface BookDao {
	public void save();
}
public class BookDaoImpl implements BookDao {

	private String databaseName;
	private int connectionNum;
	
	public void save() {
		System.out.println("book dao save ...");
	}
}
public interface UserDao {
	public void save();
}
public class UserDaoImpl implements UserDao {
	public void save() {
		System.out.println("user dao save ...");
	}
}

public interface BookService {
	public void save();
}

public class BookServiceImpl implements BookService{
	private BookDao bookDao;
	
	public void setBookDao(BookDao bookDao) {
	this.bookDao = bookDao;
	}
	public void save() {
		System.out.println("book service save ...");
		bookDao.save();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

(2)resources下提供spring的配置文件


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<property name="bookDao" ref="bookDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(3)编写AppForDIConstructor运行类,加载Spring的IOC容器,并从中获取对应的bean对象

public class AppForDIConstructor {
	public static void main( String[] args ) {
		ApplicationContext ctx = new
		ClassPathXmlApplicationContext("applicationContext.xml");
		BookService bookService = (BookService)ctx.getBean("bookService");
		bookService.save();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

接下来,在上面这个环境中来完成构造器注入的学习:

需求:将BookServiceImpl类中的bookDao修改成使用构造器的方式注入。
1.将bookDao的setter方法删除掉
2.添加带有bookDao参数的构造方法
3.在applicationContext.xml中配置

步骤1:删除setter方法并提供构造方法
在BookServiceImpl类中将bookDao的setter方法删除掉,并添加带有bookDao参数的构造方法

public class BookServiceImpl implements BookService{
	private BookDao bookDao;
	public BookServiceImpl(BookDao bookDao) {
		this.bookDao = bookDao;
	}
	public void save() {
		System.out.println("book service save ...");
		bookDao.save();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

步骤2:配置文件中进行配置构造方式注入
在applicationContext.xml中配置


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<constructor-arg name="bookDao" ref="bookDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

说明:
标签中

  • name属性对应的值为构造函数中方法形参的参数名,必须要保持一致。
  • ref属性指向的是spring的IOC容器中其他bean对象。
    步骤3:运行程序
    运行AppForDIConstructor类,查看结果,说明bookDao已经成功注入。
    在这里插入图片描述

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

需求:在BookServiceImpl使用构造函数注入多个引用数据类型,比如userDao
1.声明userDao属性
2.生成一个带有bookDao和userDao参数的构造函数
3.在applicationContext.xml中配置注入

步骤1:提供多个属性的构造函数
在BookServiceImpl声明userDao并提供多个参数的构造函数

public class BookServiceImpl implements BookService{
	private BookDao bookDao;
	private UserDao userDao;
	public BookServiceImpl(BookDao bookDao,UserDao userDao) {
		this.bookDao = bookDao;
		this.userDao = userDao;
	}
	public void save() {
		System.out.println("book service save ...");
		bookDao.save();
		userDao.save();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在applicationContext.xml中配置注入


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
	<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<constructor-arg name="bookDao" ref="bookDao"/>
		<constructor-arg name="userDao" ref="userDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

说明:这两个的配置顺序可以任意
步骤3:运行程序

运行AppForDIConstructor类,查看结果,说明userDao已经成功注入。
在这里插入图片描述

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

需求:在BookDaoImpl中,使用构造函数注入databaseName和connectionNum两个参数。
参考引用数据类型的注入,我们可以推出具体的步骤为:
1.提供一个包含这两个参数的构造方法
2.在applicationContext.xml中进行注入配置

步骤1:添加多个简单属性并提供构造方法
修改BookDaoImpl类,添加构造方法

public class BookDaoImpl implements BookDao {
	private String databaseName;
	private int connectionNum;
	public BookDaoImpl(String databaseName, int connectionNum) {
		this.databaseName = databaseName;
		this.connectionNum = connectionNum;
	}
	public void save() {
		System.out.println("book dao save..."+databaseName+","+connectionNum);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

步骤2:配置完成多个属性构造器注入
在applicationContext.xml中进行注入配置


<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="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
		<constructor-arg name="databaseName" value="mysql"/>
		<constructor-arg name="connectionNum" value="666"/>
	bean>
	<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
	<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
		<constructor-arg name="bookDao" ref="bookDao"/>
		<constructor-arg name="userDao" ref="userDao"/>
	bean>
beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

说明:这两个的配置顺序可以任意
步骤3:运行程序
运行AppForDIConstructor类,查看结果
在这里插入图片描述

2.5 解决紧耦合问题

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

  • 当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变
  • 这两块存在紧耦合,具体该如何解决?
    在解决这个问题之前,需要提前说明的是,这个参数名发生变化的情况并不多,所以上面的还是比较
    主流的配置方式,下面介绍的,大家都以了解为主。

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

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

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

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

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

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
    • 强制依赖指对象在创建的过程中必须要注入指定的参数
  2. 可选依赖使用setter注入进行,灵活性强
    • 可选依赖指对象在创建过程中注入的参数可有可无
  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  6. 自己开发的模块推荐使用setter注入

3 总结

这节中主要讲解的是Spring的依赖注入的实现方式:

  • setter注入

1.简单数据类型

<bean ...>
  <property name="" value=""/>
bean>
  • 1
  • 2
  • 3

2.引用数据类型

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

1.简单数据类型

<bean ...>
	<constructor-arg name="" index="" type="" value=""/>
bean>
  • 1
  • 2
  • 3

2.引用数据类型

<bean ...>
	<constructor-arg name="" index="" type="" ref=""/>
</bean>
  • 1
  • 2
  • 3
  • 依赖注入的方式选择上
    • 建议使用setter注入
    • 第三方技术根据情况选择
源码获取~定制咨询~非开源
微信名片
注:本文转载自blog.csdn.net的老牛源码的文章"https://blog.csdn.net/shenchengyv/article/details/134752297"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top