Spring简介以及IOC详解

Spring 简介和配置

学习目标

【应用】能够独立完成 springIOC 的快速入门
【应用】能够掌握 spring 的 bean 标签的配置
【应用】能够独立完成 bean 的对象属性注入
【应用】能够独立完成 bean 的普通属性注入
【理解】能够独立完成 bean 的集合属性注入

1、Spring 概述

1.1 spring 是什么

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架，以 IoC（Inverse Of Control：反转控制）和 AOP（Aspect Oriented Programming：面向切面编程）为内核。
提供了表现层 SpringMVC 和持久层 Spring JDBCTemplate 以及业务层事务管理等众多的企业级应用技术，还能整合开源世界众多著名的第三方框架和类库，逐渐成为使用最多的 Java EE 企业应用开源框架。

1.2 Spring 发展历程

1997 年， IBM 提出了 EJB 的思想
1998 年，SUN 制定开发标准规范 EJB1.0
1999 年，EJB1.1 发布
2001 年，EJB2.0 发布
2003 年，EJB2.1 发布
2006 年，EJB3.0 发布
Rod Johnson 罗宾・约翰逊（ Spring 之父）

Expert One-to-One J2EE Design and Development (2002) 阐述了 J2EE 使用 EJB 开发设计的优点及解决方案
Expert One-to-One J2EE Development without EJB (2004) 阐述了 J2EE 开发不使用 EJB 的解决方式（Spring 雏
形）
2021 年 7 月份发布了 Spring 的最新版本 Spring 5.3.9 通用版（正式发布的版本）

1.3 Spring 的优势 （理解）

\1. 方便解耦，简化开发

Spring 就是一个大工厂（IoC 容器），可以将所有对象的创建和依赖关系的维护工作都交给 Spring 容器管理，大大地降低了组件之间的耦合性。

\2. AOP 编程的支持

通过 Spring 的 AOP 功能，方便进行面向切面编程，许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。
如 实现对程序进行权限拦截、运行监控等功能

\3. 声明式事务的支持

可以将我们从单调烦闷的事务管理代码中解脱出来，通过声明式方式灵活的进行事务管理，提高开发效率和质量。

\4. 方便程序的测试

Spring 对 Junit4 支持，可以通过注解方便的测试 Spring 程序，测试不再是昂贵的操作，而是随手可做的事情。

\5. 方便集成各种优秀框架

Spring 不排斥各种优秀的开源框架，其内部提供了对各种优秀框架（如：Struts、Hibernate、MyBatis、Quartz 等）的直接支持。

\6. 降低 JavaEE API 的使用难度

Spring 对 JavaEE 开发中非常难用的一些 API（JDBC、JavaMail、远程调用等），都提供了封装，使这些 API 应用难度大大降低。

\7. Java 源码是经典学习范例

Spring 的源代码设计精妙、结构清晰、匠心独用，处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

1.4 Spring 的体系结构（了解）

2、Spring IoC 快速入门

2.1 IoC 的概念和作用

IoC：控制反转 (Inversion Of Control) ，就是应用本身不负责依赖对象的创建及维护，依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器，控制权的转移就是所谓反转。

简单理解：把对象的创建、初始化、销毁等工作交给 spring 容器来做。由 spring 容器控制对象的生命周期。

明确 IoC 的作用：削减计算机程序的耦合 (解除我们代码中的依赖关系)。
原来：我们在获取对象时，都是采用 new 的方式。 是主动的。
现在：我们获取对象时，跟 spring 容器要，有 spring 为我们查找或者创建对象。 是被动的。

2.2 Spring IoC 程序开发步骤

①导入 Spring 开发的基本包坐标
②编写 Dao 接口和实现类
③创建 Spring 核心配置文件
④在 Spring 配置文件中配置 UserDaoImpl
⑤使用 Spring 的 API 获得 Bean 实例

2.3 导入 Spring 开发的基本包坐标

Copy
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring‐context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

2.4 编写 Dao 接口和实现类

Copy
package com.summer.dao;
public interface UserDao {
public void save();
}

package com.summer.dao.impl;
import com.summer.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("用户添加~~~~~");
}
}

2.5 创建 Spring 核心配置文件

在类路径 classpath 下（resources）创建 applicationContext.xml 配置文件

Copy
<?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">
</beans>

2.6 在 Spring 配置文件中配置 UserDaoImpl

Copy
<?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">
<!‐‐ 实现IoC将对象的创建 交给spring容器
UserDao userDao = new UserDaoImpl();
‐‐>
<bean id="userDao" class="com.bailiban.dao.impl.UserDaoImpl"></bean>
</beans>

2.7 使用 Spring 的 API 获得 Bean 实例

Copy
public class TestIoC{
public static void main(String[] args) {
// 创建spring容器实例
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取 bean 根据 唯一标识id获取
UserDao userDao = (UserDao) context.getBean("userDao");
userDao.save();
}
}

在类路径下寻找配置文件来实例化容器
Spring 快速入门代码巩固练习
练习下通过 springIoC 的 XML 配置方式来进行对象的实例化
\1. 导入坐标
\2. 创建 Bean
\3. 创建配置文件 applicationContext.xml
\4. 在配置文件中进行配置
\5. 创建 ApplicationContext 对象 getBean

3、 Bean 的依赖注入入门

① 编写 Dao，Service 接口和实现类

Copy

public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("用户添加~~~~~");
}
}
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
public void save() {
//TODO
}
}

②将 UserDaoImpl 、 UserServiceImpl 的创建权交给 Spring

Copy
<
!‐‐ spring IoC 将对象的创建权交给spring‐‐>
<bean id="userDao" class="com.bailiban.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.bailiban.service.impl.UserServiceImpl"></bean>

UserService 内部再调用 UserDao 的 save () 方法

Copy
public class UserServiceImpl implements UserService {
public void save() {
//创建spring容器实例
ApplicationContext context = new ClassPathXmlApplicationContext();
//根据id获取dao对象
UserDao userDao = (UserDao) context.getBean("userDao");
//调用方法
userDao.save();
}
}

③从 Spring 容器中获得 UserService 进行操作

Copy

public class TestDI {
//测试 DI快速入门
@Test
public void test1() {
//创建spring容器实例
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
//根据id获取dao对象
UserService userService = (UserService) context.getBean("userService");
//调用方法
userService.save();
}
}

3.1 Bean 的依赖注入分析

目前 UserService 实例和 UserDao 实例都存在与 Spring 容器中，当前的做法是在容器外部获得 UserService 实例和 UserDao 实例，然后在程序中进行结合。

因为 UserService 和 UserDao 都在 Spring 容器中，而最终程序直接使用的是 UserService，所以可以在 Spring 容器中，将 UserDao 设置到 UserService 内部。

3.2 Bean 的依赖注入概念

DI : Dependency Injection 依赖注入，需要有 IoC 的环境，Spring 创建对象的过程中，Spring 将对象依赖的属性注入到对象。

在编写程序时，通过控制反转，把对象的创建交给了 Spring，但是代码中不可能出现没有依赖的情况。

IoC 解耦只是降低他们的依赖关系，但不会消除。例如：业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系，在使用 Spring 之后，就让 Spring 来维护了。
简单的说，就是坐等框架把持久层对象传入业务层，而不用我们自己去获取。

3.3 Bean 的依赖注入方式

怎么将 UserDao 怎样注入到 UserService 内部呢？

3.3.2 set 方法

在 UserServiceImpl 中添加 setUserDao 方法

Copy
public class UserServiceImpl implements UserService {
// 定义dao成员变量
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
// //创建spring容器实例
// ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
// //根据id获取dao对象
// UserDao userDao = (UserDao) context.getBean("userDao");
// //调用方法
userDao.save();
}
}

配置 Spring 容器调用 set 方法进行注入

Copy

<bean id="userDao" class="com.bailiban.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.bailiban.service.impl.UserServiceImpl">
<!‐‐使用set方法注入
name： set方法去掉set后 首字母小写
‐‐>
<property name="userDao" ref="userDao"></property>
</bean>

set 方法

命名空间注入
P 命名空间注入本质也是 set 方法注入，但比起上述的 set 方法注入更加方便，主要体现在配置文件中，如下：
首先，需要引入 P 命名空间：

Copy
xmlns:p="http://www.springframework.org/schema/p"

其次，需要修改注入方式

Copy
<bean id="userService" class="com.bailiban.service.impl.UserServiceImpl" p:userDao‐
ref="userDao">

3.4 Bean 的依赖注入的数据类型

上面的操作，都是注入的引用 Bean，除了对象的引用可以注入，普通数据类型 等都可以在容器中进行注入。
注入数据的二种数据类型
1. 普通数据类型
2. 引用数据类型
其中引用数据类型，此处就不再赘述了，之前的操作都是对 UserDao 对象的引用进行注入的，下面将以 set 方法注入为例，演示普通数据类型的注入。
Bean 的依赖注入的数据类型
（1）普通数据类型的注入
练习：

Copy
public class UserDaoImpl implements UserDao {
//普通数据类型的注入
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void save() {
System.out.println(name+"‐‐‐"+age);
System.out.println("用户添加~~~~~");
}
}

Copy

<bean id="userDao" class="com.bailiban.dao.impl.UserDaoImpl">
<!‐‐ 普通数据的注入 ‐‐>
<property name="name" value="旺财"></property>
<property name="age" value="18"></property>