• Java后端 学习路线 笔记汇总表【黑马程序员】
  1. Spring-学习笔记01【Spring框架简介】【day01】
  2. Spring-学习笔记02【程序间耦合】
  3. Spring-学习笔记03【Spring的IOC和DI】
  4. Spring-学习笔记04【Spring的常用注解】【day02】day02资料_dbutils
  5. Spring-学习笔记05【基于XML的IOC的案例】
  6. Spring-学习笔记06【Spring的新注解】
  7. Spring-学习笔记07【银行转账案例】【day03】
  8. Spring-学习笔记08【面向切面编程AOP】
  9. Spring-学习笔记09【JdbcTemplate的基本使用】【day04】
  10. Spring-学习笔记10【Spring事务控制】

目录

01 今日课程内容介绍

02 案例中添加转账方法并演示事务问题

03 分析事务的问题并编写ConnectionUtils

04 编写事务管理工具类并分析连接和线程解绑

04.1、ConnectionUtils.java

04.2、TransactionManager.java

05 编写业务层和持久层事务控制代码并配置spring的ioc

05.1、bean.xml

06 测试转账并分析案例中的问题

06.1、AccountServiceImpl

07 代理的分析

08 基于接口的动态代理回顾

08.1、IProducer.java

08.2、Producer.java

08.3、Client.java

09 基于子类的动态代理

09.1、pom.xml

09.2、Producer.java

09.3、Client.java

10 使用动态代理实现事务控制

10.1、BeanFactory.java


01 今日课程内容介绍

今日内容

  1. 完善我们的account案例
  2. 分析案例中问题
  3. 回顾之前讲过的一个技术:动态代理
  4. 动态代理另一种实现方式
  5. 解决案例中的问题
  6. AOP的概念
  7. spring中的AOP相关术语
  8. spring中基于XML和注解的AOP配置

02 案例中添加转账方法并演示事务问题

03 分析事务的问题并编写ConnectionUtils

事务控制

04 编写事务管理工具类并分析连接和线程解绑

04.1、ConnectionUtils.java

package com.itheima.utils;import javax.sql.DataSource;
import java.sql.Connection;/*** 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定。*/
public class ConnectionUtils {private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();private DataSource dataSource;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}/*** 获取当前线程上的连接** @return*/public Connection getThreadConnection() {try {//1.先从ThreadLocal上获取Connection conn = tl.get();//2.判断当前线程上是否有连接if (conn == null) {//3.从数据源中获取一个连接,并且存入ThreadLocal中conn = dataSource.getConnection();tl.set(conn);}//4.返回当前线程上的连接return conn;} catch (Exception e) {throw new RuntimeException(e);}}/*** 把连接和线程解绑*/public void removeConnection() {tl.remove();}
}

04.2、TransactionManager.java

package com.itheima.utils;/*** 和事务管理相关的工具类,它包含了:开启事务、提交事务、回滚事务和释放连接。*/
public class TransactionManager {private ConnectionUtils connectionUtils;public void setConnectionUtils(ConnectionUtils connectionUtils) {this.connectionUtils = connectionUtils;}/*** 开启事务*/public void beginTransaction() {try {connectionUtils.getThreadConnection().setAutoCommit(false);} catch (Exception e) {e.printStackTrace();}}/*** 提交事务*/public void commit() {try {connectionUtils.getThreadConnection().commit();} catch (Exception e) {e.printStackTrace();}}/*** 回滚事务*/public void rollback() {try {connectionUtils.getThreadConnection().rollback();} catch (Exception e) {e.printStackTrace();}}/*** 释放连接*/public void release() {try {connectionUtils.getThreadConnection().close();//还回连接池中connectionUtils.removeConnection();} catch (Exception e) {e.printStackTrace();}}
}

05 编写业务层和持久层事务控制代码并配置spring的ioc

05.1、bean.xml

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--配置代理的service--><bean id="proxyAccountService" factory-bean="beanFactory" factory-method="getAccountService"></bean><!--配置beanfactory--><bean id="beanFactory" class="com.itheima.factory.BeanFactory"><!--注入service--><property name="accountService" ref="accountService"></property><!--注入事务管理器--><property name="txManager" ref="txManager"></property></bean><!--配置Service--><bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"><!--注入dao--><property name="accountDao" ref="accountDao"></property></bean><!--配置Dao对象--><bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"><!--注入QueryRunner--><property name="runner" ref="runner"></property><!--注入ConnectionUtils--><property name="connectionUtils" ref="connectionUtils"></property></bean><!--配置QueryRunner--><bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean><!--配置数据源--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><!--连接数据库的必备信息--><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property><property name="user" value="root"></property><property name="password" value="root"></property></bean><!--配置Connection的工具类 ConnectionUtils--><bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils"><!--注入数据源--><property name="dataSource" ref="dataSource"></property></bean><!--配置事务管理器--><bean id="txManager" class="com.itheima.utils.TransactionManager"><!--注入ConnectionUtils--><property name="connectionUtils" ref="connectionUtils"></property></bean>
</beans>

06 测试转账并分析案例中的问题

06.1、AccountServiceImpl

package com.itheima.service.impl;import com.itheima.dao.IAccountDao;
import com.itheima.domain.Account;
import com.itheima.service.IAccountService;import java.util.List;/*** 账户的业务层实现类* <p>* 事务控制应该都是在业务层*/
public class AccountServiceImpl implements IAccountService {private IAccountDao accountDao;public void setAccountDao(IAccountDao accountDao) {this.accountDao = accountDao;}@Overridepublic List<Account> findAllAccount() {return accountDao.findAllAccount();}@Overridepublic Account findAccountById(Integer accountId) {return accountDao.findAccountById(accountId);}@Overridepublic void saveAccount(Account account) {accountDao.saveAccount(account);}@Overridepublic void updateAccount(Account account) {accountDao.updateAccount(account);}@Overridepublic void deleteAccount(Integer acccountId) {accountDao.deleteAccount(acccountId);}@Overridepublic void transfer(String sourceName, String targetName, Float money) {System.out.println("transfer...");//2.1根据名称查询转出账户Account source = accountDao.findAccountByName(sourceName);//2.2根据名称查询转入账户Account target = accountDao.findAccountByName(targetName);//2.3转出账户减钱source.setMoney(source.getMoney() - money);//2.4转入账户加钱target.setMoney(target.getMoney() + money);//2.5更新转出账户accountDao.updateAccount(source);// int i=1/0;//2.6更新转入账户accountDao.updateAccount(target);}
}

07 代理的分析

代理

08 基于接口的动态代理回顾

08.1、IProducer.java

package com.itheima.proxy;/*** 对生产厂家要求的接口*/
public interface IProducer {/*** 销售** @param money*/public void saleProduct(float money);/*** 售后** @param money*/public void afterService(float money);
}

08.2、Producer.java

package com.itheima.proxy;/*** 一个生产者*/
public class Producer implements IProducer {/*** 销售** @param money*/public void saleProduct(float money) {System.out.println("销售产品,并拿到钱:" + money);}/*** 售后** @param money*/public void afterService(float money) {System.out.println("提供售后服务,并拿到钱:" + money);}
}

08.3、Client.java

package com.itheima.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 模拟一个消费者*/
public class Client {public static void main(String[] args) {final Producer producer = new Producer();/*** 动态代理:*  特点:字节码随用随创建,随用随加载*  作用:不修改源码的基础上对方法增强*  分类:基于接口的动态代理、基于子类的动态代理*  基于接口的动态代理:*      涉及的类:Proxy*      提供者:JDK官方*  如何创建代理对象:*      使用Proxy类中的newProxyInstance方法*  创建代理对象的要求:*      被代理类最少实现一个接口,如果没有则不能使用*  newProxyInstance方法的参数:*      ClassLoader:类加载器*          它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器。固定写法。*      Class[]:字节码数组*          它是用于让代理对象和被代理对象有相同方法。固定写法。*      InvocationHandler:用于提供增强的代码*          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。*          此接口的实现类都是谁用谁写。*/IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),producer.getClass().getInterfaces(),new InvocationHandler() {/*** 作用:执行被代理对象的任何接口方法都会经过该方法* 方法参数的含义* @param proxy   代理对象的引用* @param method  当前执行的方法* @param args    当前执行方法所需的参数* @return 和被代理对象方法有相同的返回值* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//提供增强的代码Object returnValue = null;//1.获取方法执行的参数Float money = (Float) args[0];//2.判断当前方法是不是销售if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}return returnValue;}});proxyProducer.saleProduct(10000f);}
}

09 基于子类的动态代理

09.1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itheima</groupId><artifactId>day03_eesy_02proxy</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1_3</version></dependency></dependencies>
</project>

09.2、Producer.java

package com.itheima.cglib;/*** 一个生产者*/
public class Producer {/*** 销售** @param money*/public void saleProduct(float money) {System.out.println("销售产品,并拿到钱:" + money);}/*** 售后** @param money*/public void afterService(float money) {System.out.println("提供售后服务,并拿到钱:" + money);}
}

09.3、Client.java

 

package com.itheima.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 模拟一个消费者*/
public class Client {public static void main(String[] args) {final Producer producer = new Producer();/*** 动态代理:*  特点:字节码随用随创建,随用随加载*  作用:在不修改源码的基础上对方法增强*  分类:基于接口的动态代理、基于子类的动态代理*  基于子类的动态代理:*      涉及的类:Enhancer*      提供者:第三方cglib库*  如何创建代理对象:*      使用Enhancer类中的create方法*  创建代理对象的要求:*      被代理类不能是最终类*  create方法的参数:*      Class:字节码*          它是用于指定被代理对象的字节码。*      Callback:用于提供增强的代码*          它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。*          此接口的实现类都是谁用谁写。*          我们一般写的都是该接口的子接口实现类:MethodInterceptor*/Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {/*** 执行被代理对象的任何方法都会经过该方法* @param proxy* @param method* @param args*    以上三个参数和基于接口的动态代理中invoke方法的参数是一样的* @param methodProxy:当前执行方法的代理对象* @return* @throws Throwable*/@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//提供增强的代码Object returnValue = null;//1.获取方法执行的参数Float money = (Float) args[0];//2.判断当前方法是不是销售if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}return returnValue;}});cglibProducer.saleProduct(12000f);}
}

10 使用动态代理实现事务控制

10.1、BeanFactory.java

package com.itheima.factory;import com.itheima.service.IAccountService;
import com.itheima.utils.TransactionManager;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 用于创建Service的代理对象的工厂*/
public class BeanFactory {private IAccountService accountService;private TransactionManager txManager;public void setTxManager(TransactionManager txManager) {this.txManager = txManager;}public final void setAccountService(IAccountService accountService) {this.accountService = accountService;}/*** 获取Service代理对象** @return*/public IAccountService getAccountService() {return (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(),accountService.getClass().getInterfaces(),new InvocationHandler() {/*** 添加事务的支持** @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("test".equals(method.getName())) {return method.invoke(accountService, args);}Object rtValue = null;try {//1.开启事务txManager.beginTransaction();//2.执行操作rtValue = method.invoke(accountService, args);//3.提交事务txManager.commit();//4.返回结果return rtValue;} catch (Exception e) {//5.回滚操作txManager.rollback();throw new RuntimeException(e);} finally {//6.释放连接txManager.release();}}});}
}

思人恩德想人好处,这是聚光,光则上扬招财招贵;
天天想人不好嫉妒人抱怨人,这叫招阴,阴则下降招病招祸。

Spring-学习笔记07【银行转账案例】相关推荐

  1. JavaScript学习笔记07【6个经典案例——电灯开关、轮播图、自动跳转首页、动态表格、表格全选、表单验证】

    Java后端 学习路线 笔记汇总表[黑马程序员] w3school 在线教程:https://www.w3school.com.cn JavaScript学习笔记01[基础--简介.基础语法.运算符. ...

  2. Spring学习笔记:配置单数据源

    Spring学习笔记:配置单数据源 一.Spring Boot默认数据源类型 Springboot默认支持4种数据源类型,定义在 org.springframework.boot.autoconfig ...

  3. 一箭双雕 刷完阿里P8架构师spring学习笔记+源码剖析,涨薪8K

    关于Spring的叙述: 我之前死磕spring的时候,刷各种资料看的我是一头雾水的,后面从阿里的P8架构师那里拿到这两份资料,从源码到案例详细的讲述了spring的各个细节,是我学Spring的启蒙 ...

  4. JavaEE——Spring学习笔记03【AOP开发】

    JavaEE--Spring学习笔记01[Ioc开发的模式] JavaEE--Spring学习笔记02[Spring和Mybatis的整合] JavaEE--Spring学习笔记03[AOP开发] J ...

  5. JavaEE——Spring学习笔记01【Ioc开发的模式】

    JavaEE--Spring学习笔记01[Ioc开发的模式] JavaEE--Spring学习笔记02[Spring和Mybatis的整合] JavaEE--Spring学习笔记03[AOP开发] J ...

  6. CHY的Spring学习笔记---师从动力节点王鹤老师(B站白嫖)

    Spring学习笔记 核心技术:ioc和aop ioc:使用di(依赖注入)实现控制反转,底层使用的是反射机制 spring可以创建自己写的类的对象,也可以创建非自定义对象,只要知道类的全限定名即可. ...

  7. 【Spring学习笔记-MVC-13.2】Spring MVC之多文件上传

    作者:ssslinppp       1. 摘要 前篇文章讲解了单文件上传<[Spring学习笔记-MVC-13]Spring MVC之文件上传>http://www.cnblogs.co ...

  8. Spring学习笔记(三) AOP_annotation,AOP_XML

    在学习课程以前,听说AOP有种很神秘的感觉,好像很好深的技术.其实原理很简单,使用动态代理的方式给程序增加逻辑.与此相似的有struts2中的filter拦截器. 再讲AOP之前先把需求说一下: 同S ...

  9. MySQL学习笔记07【事务、用户管理和权限管理】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  10. spring学习笔记06-spring整合junit(出现的问题,解决的思路)

    spring学习笔记06-spring整合junit(出现的问题,解决的思路) 文章目录 spring学习笔记06-spring整合junit(出现的问题,解决的思路) 3.1测试类中的问题和解决思路 ...

最新文章

  1. 简简单单搞掂恼人的Laravel 5安装
  2. HTTP缓存原理介绍
  3. CAS Client 3.2.1 配置详解
  4. 蒙特卡洛方法_【每日一题56】蒙特卡洛方法 用试验所得的频率估计事件发生概率...
  5. mysql常规使用(建立,增删改查,视图索引)
  6. 【课题总结】OpenCV 抠图项目实战(4)固定阈值抠图
  7. 第1关:创建/删除节点
  8. 784. 字母大小写全排列
  9. 雅虎的用户注册页面抽风了
  10. 背景减法——自组织算法
  11. Java从入门到放弃系列
  12. oracle市场份额情况怎样,Oracle 2013年数据库市场份额47.4 - 再居第一
  13. 小猪短租网requests库使用
  14. Hive 字符串转日期
  15. (纪中)3505. 积木【DP】
  16. DBA之路:小小DBA一年工作总结
  17. MultiValueMap
  18. vue3.0 组合式API 加加减减
  19. 如何用VBA快速批量提取多个工作表名称?
  20. zabbix php ldap off,安装zabbix时PHP ldap Warning解决方法

热门文章

  1. 因服务器升级维护 造成不便敬请谅解,《梦幻西游》2020年5月20日维护公告
  2. python建立字典读取键和值_在Python字典中动态创建键和值
  3. koreader下载_koreader下载_koreader安装_koreader最新版_koreader安卓版下载_koreader app_易玩网...
  4. 风吹来_风吹年年,雪落片片
  5. 原来Python破解受密码保护的zip文件这么简单,不保证一定成功
  6. android跑步软件,手机跑步软件哪个好_安卓手机跑步记录软件_手机跑步app【最新】-太平洋电脑网...
  7. 上海内推 | 极氪智能科技百万年薪「氪学家」项目招聘规控/感知算法工程师
  8. 偶像剪辑,一键获取:多模态联合建模的视频人物摘要
  9. 中国学霸们被世界名校集体退学,原因竟然是……
  10. 教科书上的LDA为什么长这样?