文章目录
- 前言
- 1.依赖注入简介
- 2. setter注入
- 3. 构造器注入
- 4. 自动装配
- 总结
前言
为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码以及可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)
1.依赖注入简介
1. 什么是依赖注入
- 在编程中,依赖注入是一种实现控制反转且用于解决依赖性问题的设计模式。
- 一个依赖关系指的是可被利用的一种对象 。依赖注入是将所依赖的传递给将要使用的从属对象。该服务将会变成客户端状态的一部分并传递服务给客户端,而不允许客户端来建立或寻找服务。
- 依赖注入使我们的编程代码变得松散耦合,易于管理
2. 依赖注入的分类
- 思考:P类中传递数据的方式有几种 ?
- 普通方法 (set方法)
- 构造方法
- 思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢
- 引用类型
- 简单类型(基本数据类型与String )
- 依赖注入的方式
- setter注入
1)简单类型
2)引用类型- 构造器注入
1) 简单类型
2)引用类型
3. 依赖注入的优点
- 减少依赖性:依赖注入可以消除或者减少组件间不必要的依赖性。以降低组件改变时所带来的影响组件
- 增强可重用性:减少组件依赖性可以增强组件的可重用性。如果在不同的上下文中需要某个接口的不同实现,或者只是同一实现的不同配置,则可以将该组件配置为使用该实现。无需更改代码。
- 增加代码的可测试性:依赖注入也增加了组件的可测试性。当依赖项可以注入组件时,意味着可以注入这些依赖项的模拟实现。模拟对象用于测试作为实际实现的替代,并且可以配置模拟对象的行为
- 增强代码的可读性:依赖注入可将依赖项移动到组件的接口。使得更容易看到组件中哪些具有依赖关系,从而使代码更具可读性。
- 减少依赖性承载:依赖性承载会在代码中产生大量“噪音”,使其难以阅读和维护,并且使得组件更难测试。而依赖注入可以减少依赖性承载和静态单例的使用,可以将组件完美地连接在一起
2. setter注入
1. 依赖注入 – setter注入引用类型的步骤方法(DI入门案例所用的就是setter注入引用类型)
(代码见DI入门案例)
2. 探讨引用多个引用对象(在DI入门的代码基础上编码)
- 在dao包下创建并编写UserDao接口
package org.example.dao;public interface UserDao {public void save();
}
- 在impl包下创建并编写UserDaoImpl实现类
package org.example.dao.impl;import org.example.dao.UserDao;public class UserDaoImpl implements UserDao {public void save() {System.out.println("user dao save ...");}
}
- 在BookServiceImpl实现类中setter注入UserDao
public class BookServiceImpl implements BookService{private BookDao bookDao;private UserDao userDao;//setter注入需要提供要注入对象的set方法public void setUserDao(UserDao userDao) {this.userDao = userDao;}//setter注入需要提供要注入对象的set方法public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}public void save() {System.out.println("book service save ...");bookDao.save();userDao.save();}
}
- 在核心配置类applicationContext中配置userDAO的bean,并将其注入到BookService中
- 执行模拟测试类App2
(从运行结果中可以看到多个引用类型是可以用setter注入的)
3. 依赖注入 – setter注入普通类型的步骤方法
4. 在BookDaoImpl中提供两个变量,并提供对应的setter方法(以BookDaoImpl为例)
public class BookDaoImpl implements BookDao {private String databaseName;private int connectionNum;//setter注入需要提供要注入对象的set方法public void setConnectionNum(int connectionNum) {this.connectionNum = connectionNum;}//setter注入需要提供要注入对象的set方法public void setDatabaseName(String databaseName) {this.databaseName = databaseName;}public void save() {System.out.println("book dao save ..."+databaseName+","+connectionNum);}
}
- 在核心配置类applicationContext.xml文件中配置中注入普通变量
- 模拟测试类App2类的运行结果
3. 构造器注入
(在依赖注入–setter注入的基础上编码,将依赖注入相关的代码删掉,具体见个人主页上传的代码respr_diconstouctor)
1 . 依赖注入 – 构造器注入引用类型的步骤方法
2. 在BookService类中提供构造方法
public class BookServiceImpl implements BookService {//5.删除业务层中使用new的方式创建的dao对象private BookDao bookDao;//提供构造方法public BookServiceImpl(BookDao bookDao) {this.bookDao = bookDao;}public void save() {System.out.println("book service save ...");bookDao.save();}}
3. 在核心配置类中注入BookDao相关的bean
<?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="org.example.dao.impl.BookDaoImpl"/><bean id="bookService" class="org.example.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/></bean></beans>
4. 模拟测试类App2运行结果(同理,构造器注入可以注入多个引用类型,此处省略相关代码)
5. 依赖注入 – 构造器注入普通类型的步骤和方法
6. 在BookDao中定义两个变量,并编写对应的构造器方法
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);}
}
7. 在核心配置文件配置相关属性
- 方式一:根据构造方法参数名称注入
- 方式二:根据构造方法参数类型注入
- 方式三:根据构造方法参数位置注入
8. 模拟测试类App2运行结果
- 依赖注入的选择
4. 自动装配
1. 自动装配基础知识
- 我们已经学会如何使用元素来声明 bean 和通过使用 XML 配置文件中的和元素来注入
- Spring 容器可以在不使用和 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量
- 下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用元素的 autowire 属性为一个 bean 定义指定自动装配模式
模式 | 描述 |
no | 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。 |
byName(按名称) | 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。 |
byType(按类型) | 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。 |
constructor | 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。 |
autodetect(3.0版本不支持) | Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。 |
可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合
2. 在入门案例的基础上编码(详情见个人主页spring代码资源respr_autowire模块)
3. 自动装配
- 手动配置
- 按类型自动装配(byType)
需要提供setter方法,ioc通过setter入口给bean
- 按名称装配
要确保BookDao装配bean的id与BookService中的其中一个属性名对应上
- 依赖自动装配特征
-
集合注入(比较少用)(数组,List,Set,Map,properties)
-
新建BookDao2接口及其实现类
package org.example.dao;public interface BookDao2 {public void save();
}
public class BookDaoImpl2 implements BookDao2 {//数组private int[] array;//列表private List<String> list;//集合private Set<String> set;//图private Map<String,String> map;//propertiesprivate Properties properties;//提供对应的setter方法作为ioc提供bean的入口public void setArray(int[] array) {this.array = array;}public void setList(List<String> list) {this.list = list;}public void setSet(Set<String> set) {this.set = set;}public void setMap(Map<String, String> map) {this.map = map;}public void setProperties(Properties properties) {this.properties = properties;}//编写测试方法public void save() {System.out.println("book dao save ...");System.out.println("遍历数组:" + Arrays.toString(array));System.out.println("遍历List" + list);System.out.println("遍历Set" + set);System.out.println("遍历Map" + map);System.out.println("遍历Properties" + properties);}
}
- 核心配置类文件编写
<?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="org.example.dao.impl.BookDaoImpl"/>--><!-- <bean id="bookService" class="org.example.service.impl.BookServiceImpl" autowire="byName"/>--><bean id="bookDao2" class="org.example.dao.impl.BookDaoImpl2"><!--数组注入--><property name="array"><array><value>100</value><value>200</value><value>300</value></array></property><!--list集合注入--><property name="list"><list><value>itcast</value><value>itheima</value><value>boxuegu</value><value>chuanzhihui</value></list></property><!--set集合注入--><property name="set"><set><value>itcast</value><value>itheima</value><value>boxuegu</value><value>boxuegu</value></set></property><!--map集合注入--><property name="map"><map><entry key="country" value="china"/><entry key="province" value="henan"/><entry key="city" value="kaifeng"/></map></property><!--Properties注入--><property name="properties"><props><prop key="country">china</prop><prop key="province">henan</prop><prop key="city">kaifeng</prop></props></property></bean></beans>
- 模拟测试类编写及运行结果
总结
欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)