IAccountServiceImpl
IAccountDaoImpl
转账分析事务控制的方法
连接工具类: 先直接从线程上获取连接,没有再从线程池中获取
事务管理器类
每个Dao方法
Services给每个方法,通过事务管理器,添加事务管理操作
但方法与方法之间耦合性太高,当transfermanager中的方法做了改变,serviceImpl中的方法全都需要改变
解决:动态代理
基于接口的动态代理,该类至少实现一个接口
cglib基于子类的动态代理:基于子类的动态代理,该类不能是最终类
是invokeSuper() 不是method.invoke
优化后:方法之间的耦合解决
使用只负责Dao操作的Dao实现类,不用每个方法都添加事务操作
bean.xml
原理:动态代理对象,增强方法,给方法添加事务操作
测试类中---------通过注解IoC得到Service代理对象,通过代理对象调用增强方法transfor,完成事务数据操作
获取代理对象accountService--------通过配置文件的工厂方法注入
工厂方法中----------注入accountService、txmanager,通过动态代理,增强代理对象调用的方法transfor
连接点和切入点
所有连接事务和Dao的接口,就是连接点
所有连接点,被方法增强后的方法,就是切入点
txManager就是通知,包括前置通知、后置通知、异常通知、最终通知,整个invoke方法就是一个环绕通知,而内部的invoke是环绕通知中,明确的切入点方法调用
使用XML方法配置切面 where what when
配置切面
就是切入点和通知结合-----被增强的方法要执行的主业务代码,和 需要增强的代码(公共),的执行顺序,构成一个切面()
where what when
<aop:before> 前置
<aop:after-returning> 后置
<aop:after-throwing> 异常
<aop:after> 最终
面向切面:
把一个类的方法加到另一个实现类的方法的执行过程切面中,可以指定该切面中,这些个方法的执行顺序(通知的种类)
即,等同于动态代理方增强
bean.xml中配置切面:
设置切面id---来源于那个类的通知、设置通知类型(before、after)、通知方法及切入点表达式来关联切入点方法
通常写法
aop:pointcut ----- 配置通用化的 切入点表达式(放 aop:aspect 中只能局部用)
配置切入点表达式,方便使用 <aop:pointcut id="" expression="execution(切入点表达式)">
环绕通知
<aop:around method="环绕方法" pointcut-ref=""> 会出现将切入点方法覆盖的情况
原因:
是因为,使用了环绕代理,但没有在环绕通知里,明确给出切入点方法
解决:
在增强操作的类中(Logger、事务管理器)创建专用环绕通知的方法,
使用spring提供的接口------ProceedingJoinPoint,该接口有一个方法proceed(),此方法明确切入点方法==method.invoke(参数)
通过在增强操作类中,进行proceed(),并自定义通知的顺序,实现自动通知
注解的AOP配置
准备阶段
新建的切面类
开启注解AOP支持
----------开启环绕
例子
使用AOP配置,工厂模式动态代理的 转账
1. XML配置方法:
在转账的基础上,配置aop
2. 注解配置方法:
配置一个切面类(原来txManager),在其中环绕通知(before等低版本执行顺序出错)
bean.xml中开启AOP对注解的支持
也可以用注解开启
环绕中的方法,必须加@Around注解
其他地方全使用注解
由于数据源部分的配置,用注解比较复杂,采用XML
注意:使用注解:则测试时,IAccountService的获取通过注入获取,不用容器
最简单的jdbcTemplate
------------------------------------------------------------------------------------------------------------------------------------
使用jdbcTemplate CRUD
基本使用;
1.创建容器
2.获取对象----------通过容器获得
3.执行操作
execute()
还需要配置数据源
增删改 update操作
查询方法query的使用
三个参数(sql, RowMapper<T>, Object... args)------ sql、结果集处理、参数
自定义结果集处理类(实现RowMapper<Account>)
自定义结果接处理类,实现RowMapper<Account>接口
固定结果集处理类 BeanPropertyRowMapper<Account>(Account.class)
优化:多个Dao抽取重复代码
两种方式,一种是继承JdbcDaoSupport,只能用xml给Dao注入datasource的方式来间接注入JdbcTemplate
spring 提供了一个抽象类JdbcDaoSupport,用来存放Dao的JdbcTemplate,并关联dataSource来注入(当dataSource注入后,JdbcTemplate也就注入了)
一种是自定义的AccountDaoImpl,没有抽取重复的JdbcTemplate,就可以使用注解注入
优化继承出现的问题: 抽取重复的Jdbctemplate属性,导致不能注解注入
当将Dao实现类继承JdbcDaoSupport,就不需要写Jdbctemplate属性了,Jdbctemplate在父类就定义好了,只需要通过set方法注入dataSource,就能通过dataSource关联Jdbctemplate注入(父类中定义好了)
一、Dao实现类继承JdbcDaoSupport:操作数据库
不需要设置JdbcTemplate属性和注入,也不需要用注解将Dao转为对象,
需要在xml中配置Dao映射,只需要给他的父类注入一个数据源,用set注入dataSource
因为JdbcDaoSupport中有dataSource的set方法,并且注入dataSource就能注入JdbcTemplate
由于注入了dataSource,和创建Dao对象,父类中的JdbcTemplate也进行了注入
二、Dao实现类非继承JdbcDaoSupport:操作数据库
xml中只需给jdbcTemplate注入,并关联dataSource---用构造方法注入dataSource
JdbcTemplate中包含dataSource的构造方法注入
类似account_annoioc:引用第三方类,创建类对象时,通过构造方法注入
QueryRunner中包含DataSource的构造方法注入
类似的:调用默认构造函数,创建一个对象,并存入容器
PlatformTransactionManager --- 接口 --------用于接收事务管理器
实现类 DataSourceTransactionManager ------- 真正管理事务的对象
例:在纯接口化的事务管理中,事务管理器的配置类,创建事务管理器的方法中,
返回值类型为PlatformTransactionManager,return处创建的对象是DataSourceTransactionManager
事务隔离级别
基于声明式的事务控制 (XML、注解)
spring事务控制的环境前提
一、基于XML声明式事务控制
propagation
name的命名: 以后所有查询方法,都用find开头,就可以只用两行将所有方法都区分开配置事务的通知属性
凡是以get/list/query/count开头的业务方法,都是查询方法,都可以设为只读事务
设置成只读事务,该方法里面就只能查询,不能增删改
二、基于注解的声明式事务控制
使用纯注解
1. 添加config配置类的包、配置类和配置文件
SpringConfiguration 主配置类
jdbcConfig 通用配置类
----------------------------------------数据源使用spring自带的连接池:DriverManagerDataSource
TransactionConfig 事务管理配置类
jdbcConfig.properties 存放连接信息的配置文件
Test 测试类
基于编程式的事务管理
核心容器的更新: