介绍Spring
为什么要学
Spring技术是JavaEE开发必备技能企业开发技术选型命中率>90%
- 简化开发,降低企业级开发的复杂性
- 高效整合其他技术,提高企业级应用开发与运行效率框架整合

学什么
spinrg最重要的作用就是简化来发和框架整合, 我们的学习也从这些开始
- 简化开发
- IoC
- AOP
-
- 事务处理
- 框架整合
- MyBatis
- MyBatis-plus
- Struts
- Struts2
- Hibernate
怎么学
- 学习Spring框架设计思想
- 学习基础操作,思考操作与思想间的联系
- 学习案例,熟练应用操作的同时,体会思想

什么是spring
spring官网详细介绍了spring
- 官网: spring.io

Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能

- Spring Framework: spring所有的技术都依赖Spring Framework
- Spring Boot: 简化Spring Framework的开发配置
- Spring cloud: 微服务解决方案
- 学完以上技术可以应对市场上绝大部分的开发工作
发展历程
Rod Johnson 被称为 spring之父

- Spring1.0 基于纯配置的开发方案
- Spring2.0 引入注解功能简化开发
- Spring3.0 可以不写配置, 使用纯注解的方式进行开发
- Spring4.0 紧跟JDK的升级, 调整了个别API
- Spring5.0 全面支持JDK8
Spring Framework系统架构图
Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基,
Spring4的架构已经趋于稳定, Spring5沿用Spring4的架构

Spring Framework系统结构

- 数据访问层
- Data Access: 数据访问
- Data Integration:数据集成
- JDBC 抽象层,通过
JdbcTemplate消除重复的样板代码 - ORM 集成 Hibernate、MyBatis、JPA 等 ORM 框架,提供统一操作接口
- OXM 支持对象与 XML 的映射(如 JAXB、XStream)
- Transactions 提供声明式事务(
@Transactional注解)和编程式事务管理,适配 JDBC/JTA 等场景
- Web开发
- Serviet: 基于 Servlet 的 Web 开发支持 (处理HTTP请求)
- WebSocket: 支持 WebSocket 协议,实现客户端与服务器的双向实时通信。
- Web 应用的基础功能(请求处理、文件上传等)
- AOP&Aspects
- AOP: 面向切面编程
- Aspects: AOP思想实现
- 实现横切逻辑与业务逻辑的解耦(如日志、事务、安全)
- Core container (核心容器 )
- Beans: 定义 Bean 的创建、配置、管理规则, 是 IoC 容器操作的基础
- Core: IoC 容器的核心实现,管理 Bean 的生命周期和依赖关系
- Context: 核心上下文, 提供国际化、事件传播、资源加载、企业级服务(邮件 / 调度)等功能
- SpEL: Spring表达式语言, 支持动态访问对象属性、调用方法、执行运算
- Test (集成单元测试与集成测试)
- 支持 Spring 组件的测试,集成 JUnit/TestNG,提供 Mock 对象、测试上下文等能力。
Spring Framework学习线路

核心概念
对比传统开发与Spring开发
- 传统开发

- 代码中使用的对象, 都是程序员通过new的方式创建出来呢的
- 存在的问题: 对象与程序高度耦合, 一旦对象需要变动, 程序就要大范围改动
- Spring开发

- 使用对象时, 不再使用new产生对象,由Spring提供对象
- 控制反转(IoC): 把对象的控制权由程序员转移给Spring容器, 这种思想称为控制反转
- 在Spring中, IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
- 依赖注入(DI): 开发中ben与ben之间可能存在依赖关系, Spring在创建bean的时候, 要绑定bean之间的依赖关系,称为依赖注入
- 概念小结
- Spring的核心作用让对象与程序充分解耦
- 使用IoC容器管理bean, 这个过程称为控制反转
- 在IoC容器内将有依赖关系的bean进行关系绑定, 称为依赖注入
- 得益于Spring的控制反转和依赖注入技术, 程序员在使用对象时可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
入门案例
IOC入门案例
- 导入 Spring开发的基本包坐标

- 定义Spring管理的类(接口)

- 创建 Spring核心配置文件, 一般是applicationContext.xml, 可以是其他命名

- 在 Spring配置文件中配置需要管理的bean

- 初始化IoC容易, 通过容器获得Bean

DI入门案例
- 删除使用new的形式创建对象的代码

- 提供依赖对象对应的setter方法
- IoC容器通过调用 setBookDao 方法, 完成对象的注入

- 配置service与dao之间的关系
- property标签表示配置当前bean的属性
- name属性表示配置哪一个具体的属性
- ref属性表示参照哪一个bean


- 再次运行程序

核心容器
Bean的配置
bean基础配置

- 用于配置对象交由Spring来创建。
- 默认情况下它调用的是类中的无参构造函数, 如果没有无参构造函数则不能创建成功。
// 基本属性
// id: Bean实例在Spring容器中的唯一标识
// class: Bean的全限定名称
<bean id="userDao" class="com. itheima.dao.impl.UserDaoImpl"></bean>
bean别名配置

bean作用范围配置

// 当scope的取值为singleton时
// Bean的实例化个数:1个 (创建容器时,创建一个对象)
// Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例Bean的生命周期:
// 对象创建:当应用加载,创建容器时,对象就被创建了
// 对象运行:只要容器在,对象一直活着
// 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
<bean id="userDao" class="com. itheima.dao.impl.UserDaoImpl" scope="singleton"></bean>
// 当scope的取值为prototype时
// Bean的实例化个数:多个 (每次获取对象, 都创建一个)
// Bean的实例化时机:当调用getBean0方法时实例化Bean
// 对象创建:当使用对象时,创建新的对象实例
// 对象运行:只要对象在使用中,就一直活着
// 对象销毁:当对象长时间不用时,被Java的垃圾回收器回收了
<bean id="userDao" class="com. itheima.dao.impl.UserDaoImpl" scope="prototype"></bean>
- 为什么bean默认为单例?
- 如果一个对象用一次就创建一个, 对IoC容器来说, 管理的压力就很大
- 只要类不改变, 类创建的对象就尽可能的复用, 资源利用更合理
- 适合交给容器进行管理的bean
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象不适合交给容器进行管理的bean
- 封装实体的域对象
实例化Bean的四种方式
- 无参构造方法实例化
- 提供可访问的构造方法

// 默认的创建ben的方式
// 调用无参构造方法创建对象
// 无参构造方法如果不存在,将抛出异常BeancreationException
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"></bean>
- 工厂静态方法实例化
public class StaticFactory {
public static UserDao getUserDao() {
return new UserDaoImpl();
}
}
// 调用工厂类的静态方法创建对象
// class指定工厂类
// factory-method指定工厂类中制造对象的方法
<bean id="userDao" class="com.itheima.factory.StaticFactory" factory-method"getUserDao"></bean>
- 工厂实例方法实例化
public class DynamicFactory {
public UserDao getUserDao() {
return new UserDaolmpl();
}
}
// 调用工厂类的实例方法创建对象
// 1.让spring先创建工厂类对象
<bean id="factory" class="com.itheima.factory.DynamicFactory"></bean>
// 2.再调用工厂类对象的方法创建目标对象
// factory-bean指向工厂bean
// factory-method指向工厂bean的方法
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"/>
- FactoryBean (实用)
// FactoryBean的定义
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
// 指定要返回的对象, 该对象会交由IoC容器管理
public UserDao getobject() throws Exception {
return new UserDaoImpl();
}
// 指定返回对象的类型
public Class<?> getobjectType() {
return UserDao.class;
}
// 指定对象是否单例 (一般不写)
// 返回true单例
// 返回false多例
public boolean isSingleton() {
return true;
}
}
// 使用FactoryBean工厂实例化bean
// class指向FactoryBean, FactoryBean返回什么对象, Spring就管理什么对象
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean" />
Bean生命周期配置
- 基本概念
- 生命周期: 从创建到消亡的完整过程
- bean生命周期: bean从创建到销毁的整体过程
- bean生命周期控制: 在bean创建后到销毁前做一些事情
- 方式1: 提供生命周期方法
import com. itheima. dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System out.println("save running....")
}
public UserDaoImpl() {
System out.println("UserDaoImpl创建....")
}
public void init(){
System out.println("初始化方法....")
}
public void destory() {
System out.println("销毁方法....")
}
}
// 配置声明周期方法
// init-method: 指定类中的初始化方法名称
// destroy-method: 指定类中销毁方法名称
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"></bean>
- 方式2: 实现InitializingBean,DisposableBean接口

- 特别说明:
- java程序运行在虚拟机中, 上面的程序执行完后虚拟机就会退出, 根据没有给IoC容器销毁bean的机会, 所以上面的程序中看不到bean销毁的过程
- 容器关闭前触发bean的销毁
- 手工关闭容器:
-
- ConfigurableApplicationcontext 接囗 close() 操作
- 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
-
- ConfigurableApplicationcontext接registerShutdownHook()操作

Bean的完整生命周期
初始化容器阶段
- 创建对象(内存分配 )
- 执行构造方法
- 执行属性注入(set操作 )
- 执行bean初始化方法
使用bean阶段
- 执行业务操作
关闭/销毁容器阶段
- 执行bean销毁方法
核心内容小结

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

- 配置中使用property标签ref属性注入引用类型对象

setter注入--简单类型
- 在bean中定义引用类型属性并提供可访问的set方法

- 配置中使用property标签value属性注入简单类型数据

构造器注入---引用类型(了解)
- 在bean中定义引用类型属性并提供可访问的构造方法

- 配置中使用constructor-arg标签ref属性注入引用类型对象

构造器注入--简单类型(了解 )
- 在bean中定义引用类型属性并提供可访问的set方法

- 配置中使用constructor-arg标签value属性注入简单类型数据

构造器注入--参数适配(了解 )
- 配置中使用constructor-arg标签type属性设置按形参类型注入

- 配置中使用constructor-arg标签index属性设置按形参位置注入

依赖注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
依赖自动装配
IoC容器根据bean所依赖的资源在容器中自动査找并注入到bean中的过程称为自动装配
- 自动装配方式
- 按类型(常用)
- 按名称
- 按构造方法
- 不启用自动装配
- 配置中使用bean标签autowire属性设置自动装配的类型

- 依赖自动装配特征
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
- 注入数组对象

- 注入List对象(重点)

- 注入Set对象

- 注入Map对象(重点)

- 注入Properties对象

小案例: 数据源对象管理
- 导入druid坐标

- 配置数据源对象作为spring管理的bean

- 如果使用默认的库, 坐标怎么找?

- 怎么确定参数?
- 根据名称找对象, 相关的参数会不止一个, 需要自己辨别, 不行就百度吧

- 点进去对象, Ctrl+F12 (查看所有方法), 排查是否提供了参数注入的构造方法, 如果没有的话就用setter注入

- 确定了参数的注入方式, 具体的参数名还要根据提示找, 一般不难找, 实在不行百度吧

上面的小案例中参数写死在了程序中, 更规范的形式是写在配置文件中

本节介绍加载properties文件参数的步骤
- 开启context命名空间

- 使用context命名空间,加载指定properties文件

- 使用 ${} 读取加载的属性值

- 一些注意的细节
- 不加载系统属性 (存在属性冲突使用, 比如系统存在环境变量username, 一般用不到)

- 加载多个properties文件

- 加载所有properties文件

- 加载properties文件标准格式

- 从类路径或jar包中搜索并加载properties文件 (加载整个工程的包括第三方jar包中的配置文件, 相当猛)

核心内容小结

容器的操作
创建容器
方式一: 类路径加载配置文件

方式二: 文件路径加载配置文件

加载多个配置文件 (合并的效果)

获取bean
方式一: 使用bean名称获取

方式二: 使用bean名称获取并指定类型

方式三: 使用bean类型获取

容器类层次结构

- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
- ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
- ApplicationContext接囗常用初始化类
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
BeanFactory是Spring最高层级接口
- BeanFactory是Spring1.0使用的Ioc容器接口
- 类路径加载配置文件

- BeanFactory创建完毕后,所有的bean均为延迟加载
- ApplicationContext创建完毕后, 所有的bean均为立即加载, 可以调整, 代码如下
![]()
- ApplicationContext接口的功能比BeanFactory更多, 并且扩张了若干功能子接口, 所以现在都用这个
注解开发
注解定义Bean
使用注解定义Bean的步骤
- 使用@Component定义bean

- 核心配置文件中通过组件扫描加载bean

- Spring提供@Component注解的三个衍生注解
- 衍生注解和@Componen注解的作用完全一样
- 作用就是语义更好, 方便区分bean的作用, 推荐使用
- @Controller: 用于表现层bean定义
- @Service: 用于业务层bean定义
- @Repository: 用于数据层bean定义

纯注解开发模式
Spring3.0开启了纯注解开发模式,使用ava类替代配置文件,开启了Spring快速开发赛道
- 创建配置文件类代替Spring核心配置文件
- @Configuration注解用于设定当前类为配置类
- @Configuration的作用就是告诉Spring该类是一个配置类, 解析后的内容与xml模板的内容一致

- @ComponentScan注解替代的是<context:component-scan>标签, 告诉Spring加载Bean的范围
- 只要组件在加载范围内, 并且添加了组件组件, 该组件就会被Spring Ioc容器管理
- @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

- 切换Spring创建IoC容器的方式
- 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象

Bean的管理
使用@scope定义bean作用范围

使用@PostConstruct、@PreDestroy定义bean生命周期

依赖注入
复杂类型的注入
使用 @Autowired 开启自动装配模式(按类型)

- 注意: 自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法
- 注意: 自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法
使用@Qualifier注解开启指定名称装配bean

- 注意: @Qualifier注解无法单独使用,必须配合@Autowired注解使用
- 作用: @Autowired按类型装配, 如果同一类型对象有多个, 配置会失败, 可以使用该注解按名称进行匹配
简单类型的注入
使用@Value实现简单类型注入

使用@PropertySource注解加载properties文件

- 该注解是加载配置文件类上
- 注意:路径仅支持单一文件配置,多文件请使用数组格式配置,不允许使用通配符*
- 取值的语法就是 ${}


第三bean的管理
最简单的方式: 使用@Bean配置第三方bean
- 在配置类文件中定义一个方法获得要管理的对象
- 添@Bean,表示当前方法的返回值是一个bean


- 这种方式会造成Spring配置类文件的臃肿和混乱
推荐的方式: 使用独立的配置类管理第三方bean
- 该方式是把定义Bean的方法提取到独立的文件中

- 这样提取出来, 就是个普通类文件, Spirng配置类文件扫描不到, 这个ben就无法被Spring Ioc容器管理
- 下一步的目标就是把这个独立的配置类加入核心配置
- 方式1: 导入式 (推荐使用)
- 使用@Import注解手动加入配置类到核心配置,此注解只能添加一次,多个数据请用数组格式

- 方式2: 扫描式
- 给独立的配置类加上注解

- 使用@Componentscan注解扫描配置类所在的包,加载对应的配置类信息

第三方bean依赖注入
简单类型依赖注入: 成员变量

引用类型依赖注入: 方法形参

- 引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象
XML配置与注解配置比较

框架整合
整合MyBatis
使用传统方式整合MyBatis开发
- 引入mybatis坐标

- 在应用程序中创建数据库连接, 然后查询数据 (App.Class)

- 创建数据库连接需要配置数据库连接参数, 这里使用xml配置文件的形式 (resources/SqlMapConfig.xml)


Spring整合MyBatis, 就是把MyBatis连接对象(SqlSessionFactory)交给Spring管理, 不再自己创建
- 新增两个依赖包

- 把连接数据封装成数据源对象, 并注册为bean



- 把mybatis的配置封装成配置对象, 并注册为bean


- 从spring ioc获取数据库连接对象, 查询数据

- 强调一下 配置Bean 与 配置文件 的对应关系


整合JUnit
spring整合JUnit测试框架的步骤
- 导入坐标

- 使用Spring整合Junit专用的类加载器
- @RunWith 指定JUnit的类加载器
- @ContextConfiguration 指定 Spring配置文件

1647

被折叠的 条评论
为什么被折叠?



