當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring-学习笔记07【银行转账案例】
生活随笔
收集整理的這篇文章主要介紹了
Spring-学习笔记07【银行转账案例】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- Java后端 學習路線 筆記匯總表【黑馬程序員】
目錄
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 今日課程內容介紹
今日內容
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【银行转账案例】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring-学习笔记06【spring
- 下一篇: Spring-学习笔记08【面向切面编程