1 Spring基本概念
1.1 框架
1.2 Spring
1.2.1 Spring的体系结构
1.2.2 Spring的发展史
1.3 耦合和内聚
1.4 工厂模式发展史
1.5 IoC(Inversion Of Controller)控制反转
1.6 Spring-Ioc的基本使用步骤
2 Ioc配置 - XML格式
2.1 bean- 标签
2.1.1bean -> scope - 属性
2.1.2bean - 生命周期
2.2 静态工厂与实例工厂创建bean
2.2.1 静态工厂创建bean
2.2.2 实例工厂创建bean
2.3 DI(Dependency Injection)依赖注入
2.3.1 DI和IoC的区别
2.3.2 依赖注入的两种方式
2.4 P命名空间(简化书写,不常用)
2.5 SpEL(了解)
2.6 properties文件读取
2.7 import标签 - 团队开发
2.8 ApplicationContext的对象层次结构分析
2.9 配置第三方资源
2.10 Spring整合Mybatis
3 注解形式-- IoC
3.1 注解驱动的基本概念
3.2 常用注解
3.2.1 bean注解定义格式
3.2.2 @Scope作用域注解
3.2.3 @PostConstruct @PreDestroy生命周期注解
3.2.4 @Bean - 第三方资源加载
3.2.5 属性注入注解
3.2.6 @PropertySource - properties文件加载
3.2.7 @Configuration、@ComponentScan- 纯注解
3.2.8 第三方Bean配置与管理
3.3 bean加载控制
3.3.1 依赖关系
3.3.2 顺序加载(多个Spring配置)
3.3.3 延迟加载
3.3.4 依赖加载应用场景
3.4 Spring与其他技术整合
3.4.1Spring整合Mybatis
3.4.2Spring整合Junit
3.5 IoC核心原理
3.5.1 组件扫描过滤器(@Component)- TypeFilter
3.5.2 自定义导入器(@Import)- ImportSelector
3.5.3 自定义注册器(导入器,过滤器等)- ImportBeanDefinitionRegistrar
3.6 整体工作流程图解
4 AOP
4.1 AOP基本概念
4.1.1 AOP的八个核心
4.1.2 AOP开发过程
4.2 AOP的基本使用步骤
4.3 XML方式AOP
4.3.1 切面
4.3.2 切入点
4.3.3 通知
4.4 注解方式AOP
4.4.1 XML方式转为注解
4.4.2 XML转换注解的注意事项
4.4.3 常用注解AOP
4.4.4 注解开发通知执行顺序控制
4.4.5 注解驱动
4.4.6 常用功能-- 接口耗时监控
4.5 AOP底层原理
4.5.1 静态代理
4.5.2 动态代理-- Proxy
4.5.3 动态代理-- CGLIB
4.5.4 织入时机
5 事务
5.1 事务的基本概念
5.1.1mysql内部对于事务存储数据的原理
5.2 事务管理
5.2.1 Spring事务核心对象
5.2.2 事务控制方式
5.3 事务底层原理 -- 设计模式
6 模板对象
6.1 JdbcTemplate
6.2 RedisTemplate
1 Spring基本概念
1.1 框架
框架源自于建筑学,隶属土木工程,后发展到软件工程领域.在软件工程中框架指的是经过验证的,具有一定功能的,半成品软件
框架的作用:
● 提高开发效率
● 增强可重用性
● 提供编写规范
● 节约维护成本
● 解耦底层实现原理
1.2 Spring
1.2.1 Spring的体系结构
Spring是分层的JavaSE/EE应用full-stack(一站式)轻量级开源框架.
Spring的体系结构如下:
● 底层是核心容器
● Beans
● Core
● Context
● SpringEl表达式
● 中间层技术
● AOP
● Aspects
● 应用层技术
● 数据访问与数据集成
● Web集成
● Web实现
● 基于Test测试
1.2.2 Spring的发展史
Spring是由EJB发展而来的
1.3 耦合和内聚
● 耦合(Coupling):代码书写过程中所使用技术的结合紧密度,用于衡量软件中各个模块之间的互联程度
● 内聚(Cohesion):代码书写过程中单个模块内部各组成部分间的联系,用于衡量软件中各个功能模块内部的功能联系
● 程序书写的目标:高内聚,低耦合
● 就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却不要那么紧密
1.4 工厂模式发展史

1.5 IoC(Inversion Of Controller)控制反转
● IoC(Inversion Of Control)控制反转,Spring反向控制应用程序所需要使用的外部资源
● Spring控制的资源全部放置在Spring容器中,该容器称为IoC容器

1.6 Spring-Ioc的基本使用步骤
加载spring -> 创建资源 -> 配置资源 -> 使用资源1. pom.xml中导入spring坐标(5.1.9.release)<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.9.RELEASE</version></dependency>2. 编写业务层与表现层(模拟)接口与实现类3. 建立spring配置文件(主配置文件必须为applicationContext,xml)4. 配置所需资源(Service)为spring控制的资源<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 1.创建spring控制的资源--><bean id="userService"class="com.itheima.service.impl.UserServiceImpl"/></beans>5. 表现层(App)通过spring获取资源(Service实例)//2.加载配置文件ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");//3.获取资源UserService userService = (UserService) ctx.getBean("userService");userService.save();
2 Ioc配置 - XML格式
2.1 bean - 标签

2.1.1 bean -> scope - 属性
singleton 单实例模式 在spring容器创建时进行对象构造,只创建一次,该Bean实例是共享的
prototype 多实例模式 在每次获取类对象时都进行创建

2.1.2 bean - 生命周期

2.2 静态工厂与实例工厂创建bean
2.2.1 静态工厂创建bean

2.2.2 实例工厂创建bean

2.3 DI(Dependency Injection)依赖注入
2.3.1 DI和IoC的区别
DI和Ioc实际上是同一种东西,区别在于站在不同的角度上看待,站在Spring容器的角度上叫Ioc,站在应用程序的角度叫DI.
● IoC(Inversion Of Control)控制翻转,Spring反向控制应用程序所需要使用的外部资源
● DI(Dependency Injection)依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入
2.3.2 依赖注入的两种方式
2.3.2.1 set注入(常用)
注意事项:
● 通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错
● spring会将name值的每个单词首字母转换成大写,然后再在前面拼接上”set”构成一个方法名,然后去对应的类中查找该方法,通过反射调用,实现注入

2.3.2.2 构造器注入(了解)


2.3.2.3 set注入 - 集合类型数据注入
● 注意事项:
1.ref标签代指引用数据类型,bean属性指向beans下定义的id与属性相同的bean中对应的class
2.bean标签作用和ref标签相同,区别在于bean标签中class属性定义了所指向的类






2.4 P命名空间(简化书写,不常用)

2.5 SpEL(了解)


2.6 properties文件读取
● 注意事项:SpEl中使用#{},而properties中使用${}
<context:property-placeholder只在第一次声明时生效,后面声明都无效

2.7 import标签 - 团队开发

● Spring容器加载多个配置文件
new ClassPathXmlApplicationContext("config1.xml","config2.xml");
● Spring容器中的bean定义冲突问题
● Spring容器加载多个配置文件同id的bean,后定义的覆盖先定义的
● Spring容器加载多个配置文件导入配置文件可以理解为将导入的配置文件复制粘贴到对应位置
● Spring容器加载多个配置文件导入配置文件的顺序与位置不同可能会导致最终程序运行结果不同
2.8 ApplicationContext的对象层次结构分析
了解:可以通过BeanFactory来构建对象Resource res = new ClassPathResource("applicationContext.xml");BeanFactory bf = new XmlBeanFactory(res);UserService userService = (UserService)bf.getBean("userService");


2.9 配置第三方资源

2.10 Spring整合Mybatis
1.导入Spring坐标,MyBatis坐标,MySQL坐标,Druid坐标,Spring整合MyBatis坐标
2.在业务层调用数据层接口,并实现业务方法的调用,通过Spring进行set属性注入
3.set注入添加数据值,properties读取文件数据
4.将mybatis配置成spring管理的bean(SqlSessionFactoryBean),MapperScannerConfigurer
5.使用spring环境加载业务层bean,执行操作
3 注解形式 -- IoC
3.1 注解驱动的基本概念


3.2 常用注解
3.2.1 bean注解定义格式


3.2.2 @Scope作用域注解

3.2.3 @PostConstruct @PreDestroy生命周期注解

3.2.4 @Bean - 第三方资源加载
需要被其他资源引用时需要在@Bean中设置名称,否则可以省略名称
spring会将@bean修饰的方法的返回值加入到容器当中

3.2.5 属性注入注解
3.2.5.1 @Value - 非引用类型

3.2.5.2 @Autowired,@Qualified - 引用类型

3.2.5.3 其他引用类型


3.2.6 @PropertySource - properties文件加载

3.2.7 @Configuration、@ComponentScan - 纯注解
纯注解格式下加载上下文对象使用 AnnotationConfigApplicationContextAnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

3.2.8 第三方Bean配置与管理

3.3 bean加载控制
3.3.1 依赖关系

3.3.2 顺序加载(多个Spring配置)

3.3.3 延迟加载

3.3.4 依赖加载应用场景

3.4 Spring与其他技术整合
3.4.1 Spring整合Mybatis

@Import(JDBCConfig.class)public class MybatisConfig {@Beanpublic SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);sqlSessionFactoryBean.setTypeAliasesPackage("com.river.domain");return sqlSessionFactoryBean;}@Beanpublic MapperScannerConfigurer getMapperScannerConfigurer(){MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();mapperScannerConfigurer.setBasePackage("com.river.dao");return mapperScannerConfigurer;}}
@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Bean("dataSource")public DruidDataSource getDataSource(){DruidDataSource dds = new DruidDataSource();dds.setDriverClassName(driver);System.out.println(driver);dds.setUrl(url);dds.setUsername(username);dds.setPassword(password);return dds;}
3.4.2 Spring整合Junit

3.5 IoC核心原理
3.5.1 组件扫描过滤器(@Component) - TypeFilter
开发过程中,需要根据需求加载必要的bean,排除指定bean
3.5.1.1 自定义过滤器

3.5.2 自定义导入器(@Import) - ImportSelector
1.bean只有通过配置才可以进入spring容器,被spring加载并控制
2.配置bean的方式如下:
XML文件中使用<bean/>标签配置
使用@Component及衍生注解配置
企业开发过程中,通常需要配置大量的bean,需要一种快速高效配置大量bean的方式

3.5.3 自定义注册器(导入器,过滤器等) - ImportBeanDefinitionRegistrar

3.5.4 bean初始化过程解析
● BeanFactoryPostProcessor
◆ 作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理
◆ 运行时机:当前操作用于对工厂进行处理,仅运行一次
● BeanPostProcessor
◆ 作用:定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理
◆ 运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作
● InitializingBean
◆ 作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理
◆ 运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理
● 注意:上述操作均需要被spring容器加载放可运行
繁琐的bean初始化过程处理
● FactoryBean
◆ 对单一的bean的初始化过程进行封装,达到简化配置的目的
FactoryBean与BeanFactory区别
● FactoryBean:封装单个bean的创建过程
● BeanFactory:Spring容器顶层接口,定义了bean相关的获取操作
3.6 整体工作流程图解


4 AOP
4.1 AOP基本概念
● AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
● AOP弥补了OOP的不足,基于OOP基础之上进行横向开发
◆ OOP规定程序开发以类为主体模型,一切围绕对象进行,完成某个任务先构建模型
◆ AOP程序开发主要关注基于OOP开发中的共性功能,一切围绕共性功能进行,完成某个任务先构建可能遇到的所有共性功能(当所有功能都开发出来也就没有共性与非共性之分)
● “AOP联盟”
● 伴随着AOP时代的降临,可以从各个行业的标准化、规范化开始入手,一步一步将所有共性功能逐一开
发完毕,最终以功能组合来完成个别业务模块乃至整体业务系统的开发
● 目标:将软件开发由手工制作走向半自动化/全自动化阶段,实现“插拔式组件体系结构”搭建
◆ AOP优势:
● 提高代码的可重用性
● 业务代码编码更简洁
● 业务代码维护更高效
● 业务功能扩展更便捷
4.1.1 AOP的八个核心
● Joinpoint(连接点):就是方法
!● Pointcut(切入点):就是挖掉共性功能的方法
!● Advice(通知):就是共性功能,最终以一个方法的形式呈现
!● Aspect(切面):就是共性功能与挖的位置的对应关系
● Target(目标对象):就是挖掉功能的方法对应的类产生的对象,这种对象是无法直接完成最终工作的
● Weaving(织入):就是将挖掉的功能回填的动态过程
● Proxy(代理):目标对象无法直接完成工作,需要对其进行功能回填,通过创建原始对象的代理对象实现
● Introduction(引入/引介) :就是对原始对象无中生有的添加成员变量或成员方法
4.1.2 AOP开发过程
● 开发阶段(开发者完成)
◆ 正常的制作程序
◆ 将非共性功能开发到对应的目标对象类中,并制作成切入点方法
◆ 将共性功能独立开发出来,制作成通知
◆ 在配置文件中,声明切入点
◆ 在配置文件中,声明切入点与通知间的关系(含通知类型),即切面
● 运行阶段(AOP完成)
◆ Spring容器加载配置文件,监控所有配置的切入点方法的执行
◆ 当监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置将通知对应的功能织入,完成完整的代码逻辑并运行
4.2 AOP的基本使用步骤
1. 导入相关坐标<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>2. 确认要抽取的功能,并将其制作成方法保存到专用的类中,删除原始业务中对应的功能(功能分离,实际开发过程先设计再制作)3. 将所有进行AOP操作的资源加载到IoC容器中beans标签中声明xmlns:aop的约束4. 使用配置的方式描述被抽取功能的位置,并描述被抽取功能与对应位置的关系(配置关系)<!--aop配置--><aop:config><!--配置切入点--><aop:pointcut id="pt" expression="execution(* *..*())"/><!--配置切面--><aop:aspect ref="myAdvice"><!--通知与切入点之间的关系--><aop:before method="logAdvice" pointcut-ref="pt"/></aop:aspect></aop:config>5. 运行程序
4.3 XML方式AOP
4.3.1 切面
● Aspect(切面)用于描述切入点与通知间的关系,是AOP编程中的一个概念● AspectJ是基于java语言对Aspect的实现
常用标签:
1.aop:config -- 设置AOP,在一个beans标签中可以设置多个aop:config标签,作用在于声明aop配置
2.aop:aspect -- 设置具体的AOP通知对应的切入点,在一个aop:config中可以配置多个aop:aspect标签,标签中ref属性用于指定通知所在bean的id(抽取出来的公共方法所在类)
4.3.2 切入点
aop:pointcut -- 设置切入点,一个aop:config标签中可以配置多个aop:pointcut标签,且该标签可以配置在aop:aspect标签内
● 基本属性:
◆ id :识别切入点的名称
◆ expression :切入点表达式
4.3.2.1 切入点表达式
切入点描述的是某个方法,而切入点表达式是一个快速匹配方法描述的通配格式,类似于正则表达式
切入点表达式格式:
◆ 关键字(访问修饰符 返回值 包名.类名.方法名(参数)异常名)
◆ 关键字:描述表达式的匹配模式(参看关键字列表)
◆ 访问修饰符:方法的访问控制权限修饰符
◆ 类名:方法所在的类(此处可以配置接口名称)
◆ 异常:方法定义中指定抛出的异常
范例:execution(public User com.river.service.UserService.findById(int))
常用的切入点表达式:excution -- 匹配执行指定方法
其他表达式(了解):
● args :匹配带有指定参数类型的方法
● within :……
● this :……
● target :……
● @within :……
● @target :……
● @args :……
● @annotation :……
● bean :……
● reference pointcut :……
4.3.2.2 切入点表达式通配符
1. * :单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现execution(public * com.river.*.UserService.find*(*))◆ 匹配com.river包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法2. .. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写execution(public User com..UserService.findById(..))◆ 匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法3. +:专用于匹配子类类型execution(* *..*Service+.*(..))
4.3.2.3 逻辑运算符
● && :连接两个切入点表达式,表示两个切入点表达式同时成立的匹配● || :连接两个切入点表达式,表示两个切入点表达式成立任意一个的匹配● ! :连接单个切入点表达式,表示该切入点表达式不成立的匹配
4.3.2.4 常用切入点表达式
1.匹配所有三种格式execution(* *(..))execution(* *..*(..))execution(* *..*.*(..))2.匹配所有公共的返回值为空的service包下的所有方法execution(public void com..service.*.*(..))
4.3.2.5 切入点的三种配置方式
1.公共切入点在aop:aspect标签之外声明aop:pointcut2.局部切入点在aop:aspect标签内部声明aop:pointcut3.直接切入点在aop:aspect内部的通知中手动指定pointcut属性● 示例配置<aop:config><!--配置公共切入点--><aop:pointcut id="pt1" expression="execution(* *(..))"/><aop:aspect ref="myAdvice"><!--配置局部切入点--><aop:pointcut id="pt2" expression="execution(* *(..))"/><!--引用公共切入点--><aop:before method="logAdvice" pointcut-ref="pt1"/><!--引用局部切入点--><aop:before method="logAdvice" pointcut-ref="pt2"/><!--直接配置切入点--><aop:before method="logAdvice" pointcut="execution(* *(..))"/></aop:aspect></aop:config>
4.3.2.6 XML切入点配置的一般过程
企业开发命名规范严格遵循规范文档进行,先为方法配置局部切入点,再抽取类中公共切入点,最后抽取全局切入点,代码走查过程中检测切入点是否存在越界性包含,是否存在非包含性进驻,设定AOP执行检测程序,在单元测试中监控通知被执行次数与预计次数是否匹配,设定完毕的切入点如果发生调整务必进行回归测试
4.3.3 通知
4.3.3.1 通知的类型划分
通知在aop:aspect标签中进行设置,用于指定通知在原程序哪个位置进行织入
◆ 前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
应用:数据校验
◆ 后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
应用:现场清理
◆ 返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
应用:返回值相关数据处理
◆ 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
应用:对原始方法中出现的异常信息进行处理
◆ 环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行
应用:十分强大,可以做任何事情
4.3.3.2 aop:before
作用:设置前置通知,可以在一个aop:aspect中配置多个aop:before基本属性:◆ method :在通知类中设置当前通知类别对应的方法◆ pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突◆ pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
4.3.3.3 aop:after
作用:设置后置通知,可以在一个aop:aspect中配置多个aop:after基本属性:◆ method :在通知类中设置当前通知类别对应的方法◆ pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突◆ pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
4.3.3.4 aop:after-returning
作用:设置返回后通知,可以在一个aop:aspect中配置多个aop:after-returning基本属性:◆ method :在通知类中设置当前通知类别对应的方法◆ pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突◆ pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
4.3.3.5 aop:after-throwing
作用:设置抛出异常后通知,可以在一个aop:aspect中配置多个aop:after-throwing基本属性:◆ method :在通知类中设置当前通知类别对应的方法◆ pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突◆ pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
4.3.3.6 aop:around (ProceedingJoinPoint)
作用:设置环绕通知,可以实现其他四种通知方式的功能,可以在一个aop:aspect中配置多个aop:around基本属性:◆ method :在通知类中设置当前通知类别对应的方法◆ pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突◆ pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
◆ 环绕通知是在原始方法的前后添加功能,在环绕通知中,存在对原始方法的显式调用public Object around(ProceedingJoinPoint pjp) throws Throwable {Object ret = pjp.proceed(); // 实现对原方法进行调用return ret; // 规范,需要存在返回值,返回类型为null}● 环绕通知方法相关说明:◆ 方法须设定Object类型的返回值,否则会拦截原始方法的返回。如果原始方法返回值类型为void,通知方法也可以设定返回值类型为void,最终返回null◆ 方法需在第一个参数位置设定ProceedingJoinPoint对象,通过该对象调用proceed()方法,实现对原始方法的调用。如省略该参数,原始方法将无法执行◆ 使用proceed()方法调用原始方法时,因无法预知原始方法运行过程中是否会出现异常,强制抛出Throwable对象,封装原始方法中可能出现的异常信息
4.3.3.7 多通知同时存在的执行顺序
当同一个切入点配置了多个通知时,通知会存在运行的先后顺序,该顺序以通知配置的顺序为准
4.3.3.8 通知获取数据
4.3.3.8.1 获取参数
1.所有的通知均可以获取参数,设置通知方法的首个参数为JoinPoint,通过该对象调用getArgs()方法,获取原始方法运行的参数数组public void before(JoinPoint jp) throws Throwable {Object[] args = jp.getArgs();}2.XML配置文件方式获取参数(1)通过在标签中切入点表达式添加args()选项指定获取到的参数(2)通过通知标签中的agr-name改变参数传入通知的顺序

4.3.3.8.2 获取返回值
1.aop:after-returning
在aop:after-returning标签中存在属性returning,用于指定接收到原始方法返回值名称,在通知方法中声明参数类型为Object,参数名称需要和xml中配置保持一致
2.aop:around
通过ProceedingJoinPoint类中的proceed方法获取返回值
4.3.3.8.3 获取异常
1.aop:after-throwing
在aop:after-throwing标签中存在属性throwing,用于接收原始方法抛出异常的信息,在异常通知方法中声明ThrowAble类型的参数,参数名称需要和xml配置的throwing名称保持一致
2.aop:around
通过对原始方法进行try..catch处理获取异常信息
4.4 注解方式AOP
4.4.1 XML方式转为注解
● 在XML格式基础上◆ 导入坐标(伴随spring-context坐标导入已经依赖导入完成)◆ 开启AOP注解支持<aop:aspectj-autoproxy/>◆ 配置切面@Aspect类上声明该类为一个切面@Aspect◆ 定义专用的切入点方法,并配置切入点@Pointcut切入点最终体现为一个方法,无参无返回值,无实际方法体内容,但不能是抽象方法◆ 为通知方法配置通知类型及对应切入点@Before引用切入点时必须使用方法调用名称,方法后面的()不能省略
4.4.2 XML转换注解的注意事项
1. 切入点最终体现为一个方法,无参无返回值,无实际方法体内容,但不能是抽象方法
2. 引用切入点时必须使用方法调用名称,方法后面的()不能省略
3. 切面类中定义的切入点只能在当前类中使用,如果想引用其他类中定义的切入点使用“类名.方法名()”引用
4. 可以在通知类型注解后添加参数,实现XML配置中的属性,例如after-returning后的returning属性
4.4.3 常用注解AOP
1.@Aspect -- 设置当前类为切面类@Aspectpublic class AopAdvice {}2.@Pointcut -- 使用当前方法名作为切入点引用名称,被修饰的方法忽略其业务功能,格式设定为无参无返回值的方法,方法体内空实现(非抽象)@Pointcut("execution(* *(..))")public void pt() {}3.通知 -- @Before,@After,@AfterReturning,@AfterThrowing,@Around在方法定义上方进行通知类型的声明,可以设置局部切入点也可以配置全局切入点@Around("pt()") / @Around("execution(* *..*.*(..))")
4.4.4 注解开发通知执行顺序控制
● AOP使用XML配置情况下,通知的执行顺序由配置顺序决定,在注解情况下由于不存在配置顺序的概念
的概念,参照通知所配置的方法名字符串对应的编码值顺序,可以简单理解为字母排序
◆ 同一个通知类中,相同通知类型以方法名排序为准
◆ 不同通知类中,以类名排序为准
◆ 使用@Order注解通过变更bean的加载顺序改变通知的加载顺序
● 企业开发经验
◆ 通知方法名由3部分组成,分别是前缀、顺序编码、功能描述
◆ 前缀为固定字符串,例如baidu、itheima等,无实际意义
◆ 顺序编码为6位以内的整数,通常3位即可,不足位补0
◆ 功能描述为该方法对应的实际通知功能,例如exception、strLenCheck
◆ 控制通知执行顺序使用顺序编码控制,使用时做一定空间预留
◼ 003使用,006使用,预留001、002、004、005、007、008
◼ 使用时从中段开始使用,方便后期做前置追加或后置追加
◼ 最终顺序以运行顺序为准,以测试结果为准,不以设定规则为准
4.4.5 注解驱动
1.XML中开启AOP注解支持<aop:AspectJ-AutoProxy />2.注解驱动用于代替XML开启注解支持的方式,在Spring注解配置类定义上方声明注解驱动@EnableAspectJAutoProxy@Configuration /// 代替XML文件@ComponentScan("com.river") // 设置扫描范围@EnableAspectJAutoProxy // 开启AOP注解驱动public class SpringConfig {}
4.4.6 常用功能 -- 接口耗时监控
对项目进行业务层接口执行监控,测量业务层接口的执行效率实现思想:● 测量接口执行效率:接口方法执行前后获取执行时间,求出执行时长◆ System.currentTimeMillis( )● 对项目进行监控:项目中所有接口方法,AOP思想,执行期动态织入代码◆ 环绕通知◆ proceed()方法执行前后获取系统时间实现步骤:1.定义切入点(务必要绑定到接口上,而不是接口实现类上)2.制作AOP环绕通知,完成测量功能3.注解配置AOP4.开启注解驱动支持核心方法://获取执行签名信息,pjp为方法声明参数类型的ProceddingJoinPoint的参数名称Signature signature = pjp.getSignature();//通过签名获取执行类型(接口名)String targetClass = signature.getDeclaringTypeName();//通过签名获取执行操作名称(方法名)String targetMethod = signature.getName();
4.5 AOP底层原理
4.5.1 静态代理
静态代理就是装饰者模式(Decorator Pattern):在不惊动原始设计的基础上,为其添加功能
原理:创建一个类需要实现一个接口,接口和增强方法所在类实现的接口一致,在类中创建一个方法,声明参数类型为实现的接口,在方法中调用需要增强的方法,然后添加一些其他的功能.
4.5.2 动态代理 -- Proxy
JDKProxy动态代理是针对对象做代理,要求原始对象具有接口实现,并对接口方法进行增强public StudentService save(StudentService studentService){return (StudentService) Proxy.newProxyInstance(studentService.getClass().getClassLoader(),studentService.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("save")) {System.out.println("刮大白");System.out.println("柏木板");}return method.invoke(studentService,args);}});}
4.5.3 动态代理 -- CGLIB
● CGLIB(Code Generation Library),Code生成类库
● CGLIB动态代理不限定是否具有接口,可以对任意操作进行增强
● CGLIB动态代理不需要原始被代理对象,动态创建出新的代理对象


默认在使用时检测代理对象是否实现接口,若实现接口采用JDKProxy,若未实现接口则采用CGLIBProxy代理形式,若通过proxy-target-classes属性设置为true则始终采用CGLIBProxy代理形式

4.5.4 织入时机
织入时机分为三种:编译期织入,类加载器织入,运行期织入
● Spring是在运行期进行织入的

5 事务
5.1 事务的基本概念
事务就是指数据库中多个操作合并在一起形成的操作序列
ACID -- Atomic原子性 Consistency一致性 Isolation隔离性 Durability持久性
脏读 可重复读 幻读 表锁 行锁 读锁 写锁
5.1.1 mysql内部对于事务存储数据的原理

5.2 事务管理
5.2.1 Spring事务核心对象
PlatformTransactionManager -- 平台事务管理器,接口定义了事务的基本操作DataSourceTransactionManager -- 适用于Spring JDBC或MyBatisTransactionDefinition -- 事务定义,接口定义了事务的基本信息TransactionStatus -- 事务状态,接口定义了事务在执行过程中某个时间点上的状态信息及对应的状态操作
● JPA(Java Persistence API)Java EE 标准之一,为POJO提供持久化标准规范,并规范了持久化开发的统一API,符合
JPA规范的开发可以在不同的JPA框架下运行
● JDO(Java Data Object )是Java对象持久化规范,用于存取某种数据库中的对象,并提供标准化API。与JDBC相比,
JDBC仅针对关系数据库进行操作,JDO可以扩展到关系数据库、文件、XML、对象数据库(ODBMS)等,可移植性更强
● JTA(Java Transaction API)Java EE 标准之一,允许应用程序执行分布式事务处理。与JDBC相比,JDBC事务则被限定
在一个单一的数据库连接,而一个JTA事务可以有多个参与者,比如JDBC连接、JDO 都可以参与到一个JTA事务中
5.2.2 事务控制方式

5.2.2.1 编程式
● 使用spring提供的专用于mybatis的事务管理器在业务层硬编码进行事务管理,业务层要注入dataSource对象● 将业务层的事务处理功能抽取出来制作成AOP通知,利用环绕通知运行期动态织入public Object transactionManager(ProceedingJoinPoint pjp) throws Throwable {// 定义事务管理器PlatformTransactionManager tx = new DataSourceTransactionManager();//为事务管理器设置与数据层相同的数据源tx.setDataSource(dataSource);// 定义事务定义对象TransactionDefinition definition = new DefaultTransactionDefinition();// 定义事务状态,用于控制事务执行TransactionStatus status = tx.getTransaction(definition);// 执行原方法Object ret = pjp.proceed(pjp.getArgs());// 提交事务tx.commit(status);return ret;}

5.2.2.2 声明式事务(XML)
● 由于事务管理的代码是固定的,Spring将这一操作进行了封装,通过一系列配置就可以实现事务管理,而不必编写对应的事务管理代码● 在aop:config中配置了全局的切入点,而在tx:advice中可以定义事务专属的方法匹配,进行事务管理的前提是先要匹配切入点并且匹配事务专属的方法名1.XML beans标签中声明事务管理xmlns:tx="http://www.springframework.org/schema/tx"http://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd2.定义事务管理<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>3.配置事务专属通知类<tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><!-- name可使用通配符 --><tx:method name="transfer" read-only="false"/></tx:attributes></tx:advice>4.使用aop:advisor 在AOP配置中引用事务专属通知类<aop:config><aop:pointcut id="pt" expression="execution(* *..*.transfer(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config>
5.2.2.2.1 aop:advice与aop:advisor区别
● aop:advice配置的通知类可以是普通java对象,不实现接口,也不使用继承关系● aop:advisor配置的通知类必须实现通知接口,advisor是一种特殊的advice◆ MethodBeforeAdvice◆ AfterReturningAdvice◆ ThrowsAdvice◆ ……
5.2.2.2.2 事务管理常用标签
1.tx:advice -- 用于声明事务通知◆ id :用于配置aop时指定通知器的id◆ transaction-manager :指定事务管理器bean2.tx:attributes -- 定义通知属性3.tx:method -- 设置具体的事务属性◆ 通常事务属性会配置多个,包含1个读写的全事务属性,1个只读的查询类事务属性

5.2.2.3 声明式事务(注解)
1.@Transactional // (tx:advice) -- 方法注解/类注解/接口注解,在方法定义/类定义/接口定义上方进行定义作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性2.XML:标签tx:annotation-driven -- 开启事务注解驱动,并指定对应的事务管理器<tx:annotation-driven transaction-manager="txManager"/3.配置纯注解驱动 -- @EnableTransactionManagement// (annotation-driven) -- 在Spring注解配置类上方进行声明● 开启注解驱动,等同XML格式中的注解驱动
5.2.2.4 事务传播行为
事务管理员:方法一中的事务事务协调员:方法二中的事务事务传播行为就是指方法二中的事务对于方法一中的事务的态度常用的传播属性:required supports


5.2.2.4.1 事务传播行为的应用场景

5.3 事务底层原理 -- 设计模式
● 策略模式(Strategy Pattern)使用不同策略的对象实现不同的行为方式,策略对象的变化导致行为的
变化。
● JdbcTemplate和NamedParameterJdbcTemplate等模板对象就是基于该装饰模式来进行实现的

6 模板对象
模板对象可以将每一个功能都单独拿出来作为一个模板常用模板对象有以下这些:● TransactionTemplate● JdbcTemplate● RedisTemplate● RabbitTemplate● JmsTemplate● HibernateTemplate● RestTemplate
6.1 JdbcTemplate


6.2 RedisTemplate






