1.学习目标
- 能够说出
Spring的体系结构 - 能够编写
IOC入门案例 - 能够编写
DI入门案例 - 能够配置
setter方式注入属性值 - 能够配置构造方式注入属性值
- 能够理解什么是自动装配
2.Spring简介
2.1 Spring课程介绍
1、问题导入
- 我们为什么要学习
Spring框架?
2、为什么要学
-
Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>90% -
专业角度:
- ==简化开发==:降低企业级开发的复杂性
- ==框架整合==:高效整合其他技术,提高企业级应用开发与运行效率

3、学什么
-
简化开发:
IOC(反转控制)AOP(面向切面编程)- 事务处理
-
框架整合:
MyBatisMyBatis-plusStrutsStruts2Hibernate- ……
4、怎么学
- 学习
Spring框架设计思想 - 学习基础操作,思考操作与思想间的联系
- 学习案例,熟练应用操作的同时,体会思想
2.2 初识Spring
1、Spring家族
- 官网:spring.io
Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能

2、Spring发展史

2.3 Spring体系结构
1、Spring Framework系统架构图
Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基
4.x版本的架构图
2、Spring Framework课程学习路线
2.4 Spring核心概念
1、问题导入
-
问题1:目前我们的代码存在什么问题以及怎么解决这些问题?
-
问题2:请描述什么是IOC,什么是DI?
2、目前我们代码存在的问题
- 代码书写现状:耦合度偏高
- 解决方案:使用对象时,在程序中不要主动使用
new产生对象,转换为由外部提供对象
3、核心概念
-
IOC(Inversion of Control):控制反转- 使用对象时,由主动
new产生对象转换为由==外部==提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转 - 通俗的讲就是:将
new对象的权利交给Spring,我们从Spring中获取对象使用即可
- 使用对象时,由主动
-
Spring技术对IoC思想进行了实现:Spring提供了一个容器,称为==IOC容器==,用来充当IoC思想中的“外部”IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为==Bean==
-
DI(Dependency Injection):依赖注入- 在容器中建立
bean与bean之间的依赖关系的整个过程,称为依赖注入
- 在容器中建立
4、Spring核心思想小结
- 目标:充分解耦
- 使用
IoC容器管理bean(IOC) - 在
IoC容器内将有依赖关系的bean进行关系绑定(DI)
- 使用
- 最终效果:
- 使用对象时不仅可以直接从
IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
- 使用对象时不仅可以直接从
3.IoC入门案例
3.1 思路分析
- 管理什么?(
Service和Dao) - 如何将被管理的对象告知
IoC容器?(配置) - 被管理的对象交给
IoC容器,如何获取到IoC容器?(接口) IoC容器得到后,如何从容器中获取bean?(接口方法)- 使用
Spring导入哪些坐标?(pom.xml)
3.2 原始方式创建对象
1、说明
- 创建对象是我们自己手动通过
new关键字创建的
2、dao层
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
3、service层
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao=new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
4、main方法中
package com.itheima;
import com.itheima.service.BookService;
import com.itheima.service.impl.BookServiceImpl;
public class App {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
bookService.save();
}
}
5、效果
3.3 IoC方式创建对象
1、导包
- 在
pom.xml文件中导入spring框架的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
- 刷新一下,然后才能创建
spring的配置文件
2、创建配置文件
- 在
resources目录下创建配置文件applicationContext.xml:
<?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">
<!-- 1. 导入spring的坐标spring-context,对应版本是5.2.10.RELEASE -->
<!-- 2. 配置bean: -->
<!--
bean标签:表示配置bean
id属性:表示给bean起名字
class属性:表示给bean定义类型
-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl2"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl2" />
</beans>
问题:spring配置文件提示:application context not configured for this file
3、dao层
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
4、service层
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl2 implements BookService {
private BookDao bookDao=new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
5、main方法中
package com.itheima;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
// 3. 获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 4. 获取bean(根据bean配置id获取)
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
6、效果

7、总结
- 导入
Spring坐标 - 定义
Spring管理的类(接口) - 创建
Spring配置文件,配置对应类作为Spring管理的bean。注意事项:bean定义时id属性在同一个上下文中不能重复 - 初始化
IoC容器(Spring核心容器/Spring容器),通过容器获取bean
4.DI入门案例
4.1 思路分析
- 基于
IoC管理bean Service中使用new形式创建的Dao对象是否保留?(否)Service中需要的Dao对象如何进入到Service中?(提供方法)Service与Dao间的关系如何描述?(配置)
4.2 Dao层
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl3 implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
4.3 service层
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
public class BookServiceImpl3 implements BookService {
// 5. 删除业务层中使用new的方式创建的dao对象
// private BookDao bookDao=new BookDaoImpl();
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 6. 提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
4.4 配置文件
- 默认通过
setXX方法进行引用对象的赋值
<?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">
<!-- 1. 导入spring的坐标spring-context,对应版本是5.2.10.RELEASE -->
<!-- 2. 配置bean: -->
<!--
bean标签:表示配置bean
id属性:表示给bean起名字
class属性:表示给bean定义类型
-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl3"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl3">
<!-- 7. 配置server与dao的关系 -->
<!--
property标签:表示配置当前bean的属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean,即对应的 bean 标签的 id
-->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>
4.5 图解

4.6 效果
4.7 总结
- 删除使用
new的形式创建对象的代码 - 提供依赖对象对应的
setter方法 - 配置
service与dao之间的关系
5.Bean的基础配置
5.1 问题导入
-
问题1:在
<bean>标签上如何配置别名? -
问题2:
Bean的默认作用范围是什么?如何修改?
5.2 Bean基础配置
5.3 Bean别名配置
1、语法
2、Dao层
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
3、service层
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
4、配置文件
applicationContext.xml中的代码:
<?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">
<!-- 1、name 属性:为bean指定别名,别名可以有多个,可以使用逗号、分号、空格进行分隔 -->
<!-- 2、ref 属性的值可以是一个 bean 的 id 值,也可以是一个 bean 的 name 值 -->
<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" />
</beans>
5、测试
package com.itheima;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForName {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 1、传入 name 值获取对象
BookService bookService = (BookService) ctx.getBean("service");
bookService.save();
System.out.println("----------------");
bookService = (BookService) ctx.getBean("service4");
bookService.save();
System.out.println("----------------");
bookService = (BookService) ctx.getBean("bookEbi");
bookService.save();
}
}
6、效果

7、图解
- ==代码演示==:
- ==打印结果==:
5.4 Bean作用范围配置
1、语法
扩展:scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。
2、Dao层
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
3、service层
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
4、配置文件
applicationContext.xml中的代码:
<?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">
<!-- 1、name 属性:为bean指定别名,别名可以有多个,可以使用逗号、分号、空格进行分隔 -->
<!-- 2、ref 属性的值可以是一个 bean 的 id 值,也可以是一个 bean 的 name 值 -->
<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
<!-- 3、scope:为bean设置作用范围,可选值为单例singloton,非单例prototype -->
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
</beans>
5、测试
package com.itheima;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForScope {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao1);
System.out.println(bookDao2);
}
}
6、效果
- 默认情况下为单例:

- 修改后为多例:

7、图解
- ==代码演示==:
- ==打印结果==:
最后给大家说明一下:在我们的实际开发当中,绝大部分的
Bean是单例的,也就是说绝大部分Bean不需要配置scope属性
5.5 bean作用范围说明
- 为什么
bean默认为单例? - 适合交给容器进行管理的
bean- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 不适合交给容器进行管理的
bean- 封装实体的域对象
6.Bean的实例化
6.1 Bean是如何创建的
bean本质上就是对象,创建bean使用构造方法完成
6.2 实例化Bean的三种方式
- 构造方法方式【重点】
- 静态工厂方式
- 实例工厂方式
6.3 构造方法方式
1、Dao层实现类
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public BookDaoImpl() {
System.out.println("book dao constructor is running ....");
}
public void save() {
System.out.println("book dao save ...");
}
}
2、配置文件
applicationContext.xml中的代码:
<?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">
<!-- 1、方式一:构造方法实例化bean -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>
3、测试
package com.itheima;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceBook {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
- 运行结果:
注意:无参构造方法如果不存在,将抛出异常
BeanCreationException
6.4 静态工厂方式
1、Dao层实现类
OrderDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.OrderDao;
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ...");
}
}
2、工厂类
OrderDaoFatory中的代码:
package com.itheima.factory;
import com.itheima.dao.OrderDao;
import com.itheima.dao.impl.OrderDaoImpl;
// 静态工厂创建对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup....");
return new OrderDaoImpl();
}
}
3、配置文件
applicationContext.xml配置文件:
<!-- 2、方式二:使用静态工厂实例化bean -->
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>

4、测试
AppForInstanceOrder.java中的代码:
package com.itheima.factory;
import com.itheima.dao.OrderDao;
import com.itheima.dao.impl.OrderDaoImpl;
// 静态工厂创建对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup....");
return new OrderDaoImpl();
}
}
- 运行结果:

6.5 实例工厂方式
1、Dao层实现类
UserDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao save ...");
}
}
2、工厂类
OrderDaoFatory中的代码:
package com.itheima.factory;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
// 实例工厂创建对象
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
3、配置文件
applicationContext.xml配置文件:
<!-- 3、方式三:使用实例工厂实例化bean -->
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>

4、测试
AppForInstanceOrder.java中的代码:
package com.itheima;
import com.itheima.dao.OrderDao;
import com.itheima.dao.UserDao;
import com.itheima.factory.OrderDaoFactory;
import com.itheima.factory.UserDaoFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceUser {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) ctx.getBean("userDao");
UserDao userDao2 = (UserDao) ctx.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
userDao1.save();
}
}
- 运行结果:

6.6 实现FactoryBean<T>方式
- 定义
UserDaoFactoryBean实现FactoryBean\<UserDao>UserDaoFactoryBean中实例化什么类型的对象泛型就是该类型
package com.itheima.factory;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;
// FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
// 代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
}
- 修改
applicationContext.xml配置文件
<!-- 4、方式四:使用FactoryBean实例化bean -->
<bean id="userDao1" class="com.itheima.factory.UserDaoFactoryBean"/>
- 测试:
package com.itheima;
import com.itheima.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceUser1 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) ctx.getBean("userDao1");
UserDao userDao2 = (UserDao) ctx.getBean("userDao1");
System.out.println(userDao1);
System.out.println(userDao2);
userDao1.save();
}
}
- 效果:

7.Bean的生命周期
7.1 问题导入
-
问题1:多例的
Bean能够配置并执行销毁的方法? -
问题2:如何做才执行
Bean销毁的方法?
7.2 生命周期相关概念介绍
- 生命周期:从创建到消亡的完整过程
bean生命周期:bean从创建到销毁的整体过程bean生命周期控制:在bean创建后到销毁前做一些事情
7.3 Bean生命周期控制:方式一
- ==第一步==:提供生命周期控制方法
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
// 1、表示bean初始化对应的操作
public void init(){
System.out.println("init...");
}
// 2、表示bean销毁前对应的操作
public void destory(){
System.out.println("destory...");
}
}
- ==第二步==:修改
applicationContext.xml配置文件
<!-- 1、init-method:设置bean初始化生命周期回调函数 -->
<!-- 2、destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
- ==第三步==:测试
package com.itheima;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForLifeCycle {
public static void main( String[] args ) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
// 1、注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
// ctx.registerShutdownHook();
// 2、关闭容器
ctx.close();
}
}
- ==效果==:

7.4 Bean生命周期控制:方式二
- 实现
InitializingBean, DisposableBean接口,重写afterPropertiesSet、destroy方法
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
System.out.println("set .....");
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void destroy() throws Exception {
System.out.println("service destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
}
- 修改
applicationContext.xml配置文件:
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
- 效果:

7.5 Bean生命周期过程
- 初始化容器
- 创建对象(内存分配)
- 执行构造方法
- 执行属性注入(set操作)
- 执行
bean初始化方法
- 使用
bean- 执行业务操作
- 关闭/销毁容器
- 执行
bean销毁方法
- 执行
7.6 Bean销毁时机
- 容器关闭前触发
bean的销毁 - 关闭容器方式:
- 手工关闭容器:
ConfigurableApplicationContext接口close()操作 - 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机:
ConfigurableApplicationContext接口registerShutdownHook()操作
- 手工关闭容器:
public class AppForLifeCycle {
public static void main( String[] args ) {
//此处需要使用实现类类型,接口类型没有close方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
ctx.registerShutdownHook();
//关闭容器
//ctx.close();
}
}
8.依赖注入(DI配置)
8.1 问题导入
- 思考:向一个类中传递数据的方式有几种?
- 普通方法(
set方法) - 构造方法
- 普通方法(
- 思考:依赖注入描述了在容器中建立
bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢?- 引用类型
- 简单类型(基本数据类型与
String)
8.2 依赖注入的两种方式
-
setter注入- 简单类型
- 引用类型(很常用)
-
构造器注入
- 简单类型
- 引用类型
8.3 setter方式注入
1、图解
- ==引用类型==:

- ==简单类型==:
2、示例
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
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);
}
}
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.service.BookService;
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();
}
}
- 配置文件:
<?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">
<!-- 2、注入简单类型 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<!--
property标签:设置注入属性
name属性:设置注入的属性名,实际是set方法对应的名称
value属性:设置注入简单类型数据值
-->
<property name="connectionNum" value="100"/>
<property name="databaseName" value="mysql"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<!-- 1、注入引用类型 -->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<!--
property标签:设置注入属性
name属性:设置注入的属性名,实际是set方法对应的名称
ref属性:设置注入引用类型bean的id或name
-->
<property name="bookDao" ref="bookDao"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
- 测试:
package com.itheima;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForDISet {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
- 效果:

8.4 构造方式注入
1、图解
- ==引用类型==:
- ==简单类型==:
2、示例
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.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);
}
}
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.service.BookService;
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();
}
}
- 配置文件:
<?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">
<!-- 1、根据构造方法参数名称注入 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<!--
name 属性:形参的名称
value 属性:形参的值
-->
<constructor-arg name="connectionNum" value="10"/>
<constructor-arg name="databaseName" value="mysql"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/>
</bean>
</beans>
- 测试:
public class AppForDIConstructor {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
- 效果:

3、参数适配:图解
4、参数适配:示例
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.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);
}
}
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.service.BookService;
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();
}
}
- 配置文件:
<?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">
<!-- 2、根据构造方法参数类型注入,解决形参名称的问题,与形参名不耦合 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<!--
type 属性:形参的类型
value 属性:形参的值
-->
<constructor-arg type="int" value="10"/>
<constructor-arg type="java.lang.String" value="mysql"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/>
</bean>
</beans>
- 测试:
public class AppForDIConstructor {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
5、位置适配
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.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);
}
}
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.UserDao;
import com.itheima.service.BookService;
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();
}
}
- 配置文件:
<?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">
<!-- 3、根据构造方法参数位置注入,解决参数类型重复问题,使用位置解决参数匹配-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg index="0" value="mysql"/>
<constructor-arg index="1" value="100"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="bookDao" ref="bookDao"/>
</bean>
</beans>
- 测试:
public class AppForDIConstructor {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
8.5 依赖注入方式选择
- 强制依赖使用构造器进行,使用
setter注入有概率不进行注入导致null对象出现 - 可选依赖使用
setter注入进行,灵活性强 Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用
setter注入完成可选依赖的注入 - 实际开发过程中还要根据实际情况分析,如果受控对象没有提供
setter方法就必须使用构造器注入 - 自己开发的模块推荐使用
setter注入
8.6 依赖自动装配
1、自动装配概念
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配- 自动装配方式
- ==按类型(常用)==
- 按名称
- 按构造方法
- 不启用自动装配
2、自动装配类型
- 配置中使用
bean标签autowire属性设置自动装配的类型
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
3、示例
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.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);
}
}
BookServiceImpl.java中的代码:
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
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();
}
}
- 配置文件:
<?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 class="com.itheima.dao.impl.BookDaoImpl"/>
<!-- autowire属性:开启自动装配,通常使用按类型装配 -->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
</beans>
- 测试:
public class AppForDIConstructor {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
4、依赖自动装配特征
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(
byType)必须保障容器中相同类型的bean唯一,推荐使用 - 使用按名称装配时(
byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用 - 自动装配优先级低于
setter注入与构造器注入,同时出现时自动装配配置失效
8.7 集合注入
1、注入数组类型数据
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
2、注入List类型数据
<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>
3、注入Set类型数据
<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>
4、注入Map类型数据
<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>
5、注入Properties类型数据
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>
说明:property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签
6、示例
BookDaoImpl.java中的代码:
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import java.util.*;
public class BookDaoImpl implements BookDao {
private int[] array;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
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="com.itheima.dao.impl.BookDaoImpl">
<!-- 1、数组注入 -->
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
<!-- 2、list集合注入 -->
<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>
<!-- 3、set集合注入 -->
<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>
<!-- 4、map集合注入 -->
<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>
<!-- 5、Properties注入 -->
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>
</bean>
</beans>
- 测试:
package com.itheima;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForDICollection {
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
- 效果:
