Spring
Spring
一 概述
1 简介
- 轻量级开源JavaEE框架
- 解决企业应用开发
- IOC控制反转:把创建对象的过程交给Spring处理
- AOP面向切面:不修改源代码进行功能增强
2 特点
- 方便解耦
- AOP编程支持
- 方便测试
- 方便集成框架
- 方便进行事务操作
3 Spring5.x
4 下载Spring
https://repo.spring.io/ui/native/release/org/springframework/spring/
5 Spring demo
引入包->创建对象->xml注解
二 IOC容器
0 概念
- IOC:控制反转,把对象的创建和对象之间的调用过程交给Spring管理,目的是为了降低耦合度
1底层原理
耦合度较高,通过工厂模式降低耦合度:
使用IOC再降低耦合度(UserDao变化了只需要修改xml配置)
2 IOC接口
- IOC思想基于IOC容器实现,IOC容器底层就是对象工厂
- Spring提供IOC容器实现的两种方式(两个接口)
- BeanFactory:IOC容器的实现,Spring的内部使用接口,不提供开发人员进行使用
- 加载配置文件的时候不会创建对象,获取对象的时候才创建
- ApplicationContext:BeanFactory子接口,提供更多的功能,面向开发人员
- 加载配置文件的时候就创建了对象
- BeanFactory:IOC容器的实现,Spring的内部使用接口,不提供开发人员进行使用
3 IOC操作Bean管理(基于XML)
Bean管理(指的是两个操作)
- Spring创建对象
- Spring注入属性
Bean管理两种方式:基于xml和基于注解
基于xml创建对象
- 在Spring的配置文件中使用bean标签,在标签里面添加对应属性
- bean标签中的属性
id
:唯一标识class
:类的全路径name
:和id类似,但是name中可以添加特殊字符(不用)
- 创建对象的时候,默认执行无参构造
- bean标签中的属性
- 在Spring的配置文件中使用bean标签,在标签里面添加对应属性
基于xml注入属性
DI:依赖注入,就是注入属性
方式1:使用set方法
首先在类中定义相关属性的set方法,然后修改xml配置
方式2:有参构造注入
注入空值
注入属性-外部bean
在xml中配置
注入属性-内部bean
用于设置对象属性
级联赋值
注入集合属性
注入数组类型属性
注入List类型属性
注入Map集合类型属性
集合中设置对象类型的值
抽取出公共集合
在Spring中引入名称空间util
使用util标签完成集合类型注入
3IOC操作Bean管理(FactoryBean)
- Spring有两种Bean:普通Bean和工厂Bean
- 普通Bean:在配置文件中定义bean类型就是返回类型
- 工厂Bean:在配置文件中定义bean类型可以和返回类型不一样
- 创建工厂Bean
- 创建类,让这个类作为工厂bean,实现接口FactoryBean
- 实现接口的方法,在实现的方法中定义返回的bean类型
5IOC操作Bean管理(Bean的作用域和生命周期)
- 在Spring里面可以设置创建的bean实例是单实例还是多实例,Spring中默认的情况下,创建的bean是单实例对象
- 设置单实例和多实例
- bean标签中scope属性
- singleton,单实例(默认),加载xml配置文件的时候就创建了
- prototype,多实例 ,每次调用的时候才创建
- request
- session
- bean标签中scope属性
- 生命周期
- 通过构造器创建bean实例(无参)
- 为bean中的属性设置,和对bean 的引用(调用set方法)
- 调用bean中初始化的方法(需要进行配置初始化方法)
- bean可以使用
- 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
6IOC操作Bean管理(xml自动装配)(用的少)
根据指定装配规则,Spring自动将匹配的属性值进行注入
7IOC操作Bean管理(外部属性文件)
经常用在数据库配置中
直接配置数据库信息
如果要修改则要改xml文件,很麻烦
通过引入外部属性文件配置数据库信息、
读取外部的propereties属性文件引入到Spring配置中
首先创建名称空间
然后引入
8IOC操作Bean管理(基于注解)
注解是代码中特殊的标记,格式:
@注解名称(属性名称=属性值, 属性名称=属性值...)
目的:简化xml配置
Spring针对Bean管理中创建对象提供注解
@Component
@Service
@Controller
@Repository
注:上面四个注解功能是一样的,都可以用来创建bean实例
基于注解方式实现对象的创建
引入依赖
开启组件扫描
配置文件中引入名称空间
开启组件扫描
创建类,在类上添加注解,注解中的value相当于bean中的id值
注意
只扫描
@Controller
不扫描
@Controller
基于注解实现属性的注入
注解
AutoWired
:根据属性类型进行自动装配Qualifier
:根据属性名进行注入Resource
:可以根据类型也可以根据名称@Value
:普通注入
AutoWired
添加创建对象的注解(在类上面)
在service中注入dao对象,在service类型添加dao类型属性,在属性上使用注解
Qualifier
要和
AutoWired
一起使用,当接口有多个实现类的时候就需要根据指定的实现类的名称来注入了
Value
完全注解开发(实际中用SpringBoot实现)
创建配置类,替代xml配置文件
编写测试方法
- 加载配置类->获得相关类->实现方法
三 AOP
0 概念
AOP-面向切面编程
目的:降低耦合度 ,隔离代码中的各个部分,不修改源代码实现功能的添加
底层原理:动态代理
有接口,使用JDK动态代理
创建接口实现类的代理对象来增强实现类的功能
使用Proxy类中的方法
newProxyInstance
- 三个参数:ClassLoader类加载器,类的接口(支持多个),InvocationHandler(实现这个接口创建代理对象)
步骤
创建接口
接口实现类
使用Proxy创建接口代理对象
- 主要是实现InvocationHandler中的invoke方法,也就是增强的部分
没有接口,使用CGLIB动态代理
创建当前类子类的代理对象
术语:
- 连接点:可以被增强的方法
- 切入点:实际被增强的方法
通知(增强):
- 实际增强的逻辑部分称为通知(增强)
- 通知的多种类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
切面:是一个动作——把通知用到切入点的动作
1 AOP操作
Spring框架一般都是基于AspectJ实现AOP操作
Aspect J不是Spring的组成,独立于AOP框架,一般AspectJ和Spring一起使用进行AOP
基于xml和基于注解的实现
依赖
切入点表达式
- 作用:知道对哪个类的哪个方法增强
- 语法结构
execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
- 例如:
execution(* com.atguigu.dao.Bookdao.add(..))
- *表示所有的修饰符,返回类型为void省略不写(空格代替)
execution(* com.atguigu.dao.Bookdao.*(..))
- 对所有方法增强
- 例如:
AspectJ操作(基于注解)
创建类,定义方法
创建增强类(编写增强逻辑)
进行通知的配置
在Spring的配置文件中开启注解扫描
使用注解创建User和UserProxy对象
在增强类上面添加注解
@Aspect
- UserProxy上面
在Spring配置文件中开启生成代理对象
配置不同类型的通知
在增强类里面,作为通知方法上添加通知类型
注:
共同切入点抽取,在通知的value那里设置
多个增强类对同一个方法的增强,设置增强优先级
在增强类上面加注解
@Order(数字类型值)
,值越小优先级越高
AspectJ操作(基于xml)
一般用的注解,配置文件比较麻烦
创建两个类,增强类和被增强类,创建方法
在Spring配置文件中创建两个类对象
在Spring配置文件中配置切入点
四 JdbcTemplate
0概念
- Spring对Jdbc封装,使用JdbcTemplate方便实现对数据操作
1 准备工作
引入依赖
事务
整合其他框架(如Mybatis)
在Spring配置文件中配置数据库连接池
配置JdbcTemplate对象,注入DataSource
- 创建service类,创建dao类,在dao类注入jdbctemplate
2 操作数据库
对数据库表创建实体类
编写service和dao
在dao进行数据库添加操作
JdbcTemplate.update(String sql, Object... args)
第二个参数为可变参数
删改调用的函数也是一样的
查询
返回值
JdbcTemplate.queryForObject(String sql, Class<T> requiredType)
- requiredType:返回类型的class
返回对象
JdbcTemplate.queryForObject(String sql, RowMapper<T> rowMapper, Object...args)
- rowMapper:RowMapper是接口,返回不同类型数据,使用这个接口的实现类完成数据的封装(BeanPropertyRowMapper)
- requiredType:sql语句的值
返回集合(注意方法名和前两个不一样)
JdbcTemplate.query(String sql, RowMapper<T> rowMapper, Object...args)
- rowMapper:RowMapper是接口,返回不同类型数据,使用这个接口的实现类完成数据的封装(BeanPropertyRowMapper)
- requiredType:sql语句的值
批量添加操作
JdbcTemplate.batchUpdate(String sql, List<Object[]> batchArgs)
- batchArgs:List集合,添加多条记录
底层会遍历batchArgs数组,分别执行sql语句实现批量的添加
批量修改删除操作(同添加)
五 事务
0 概念
Spring5 特性
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果一个失败则所有操作都失败。
事务的四大特性(ACID)
- 原子性:操作不可分割(要么都成功或者都失败)
- 一致性:操作前后总量不变
- 隔离性:多人操作不干涉
- 持久性
银行转账
可能在转账过程中出现异常导致一方减钱一方不变,这时候需要进行异常判断并进行事务的回滚
1 Spring事务
- 一般添加到service层中(业务逻辑层)
在Spring中的事务管理
- 编程式事务管理(一般不用)
- 声明式事务管理
声明式事务管理
- 基于xml配置文件方式
- 基于注解方式
在Spring进行声明式事务管理,底层使用AOP
Spring事务管理API
提供一个接口,代表事务管理器,这个接口针对不同的框架实现不同的实现类
2 事务操作(注解声明式事务管理)
Spring配置文件中创建事务管理器并注入数据源
引入名称空间
开启事务注解
在service类上面(或者在service类里面的方法上面)添加事务注解
@Transactional
:在类上面则这个类所有的方法都添加了事务,在方法上面就只有该方法添加了事务参数说明
Propagation
:事务的传播行为Isolation
:隔离级别事务有三个读问题:脏读、不可重复读、虚(幻)读
- 脏读:一个未提交事务读取到另一个未提交事务的数据
- 不可重复读:一个未提交事务读取到另一个提交事务修改数据
- 虚读:一个未提交事务读取到另一个提交事务添加数据
解决方式:通过设置事务的隔离级别解决读问题
timeout
:超时时间- 事务需要在一定时间内进行提交,如果不提交则回滚
- 默认值是-1,设置时间以秒未单位计算
readonly
:是否只读- 默认值false,表示可以增删改查
- 设为true后只能查询
rollbackFor
:回滚- 设置出现哪些异常进行事务回滚
noRollbackFor
:不回滚- 设置出现哪些异常不进行事务回滚
3 事务操作(xml方式)
step1 配置事务管理器
step2 配置通知
step3 配置切入点和切面
4 事务操作(完全注解开发)
step1 编写配置类
1.1 在里面创建数据库连接池
1.2 创建jdbcTemplate对象
1.3 创建事务管理器
step2 测试