- 事务使用的地方
service层 - 事务配置
package com.spring.utils; /** * 和事务相关的工具类,它3包含了,开启事务,提交事务、回滚事务、释放事务 */ public class TransactionManagement { 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(); }catch (Exception e){ e.printStackTrace(); } } }
-
配置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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--配置service层--> <bean id="accountService" class="com.spring.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> <property name="txManagement" ref="transactionManagement"></property> </bean> <!--配置dao层--> <bean id="accountDao" class="com.spring.dao.AccountDaoImpl"> <property name="queryRunner" ref="queryRunner"></property> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置QueryRunner--> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean> <!--配置数据源--> <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://120.25.236.19:3306/practice?useSSL=false"></property> <property name="user" value="root"></property> <property name="password" value="123456"></property> </bean> <!--配置Connection的工具类--> <bean id="connectionUtils" class="com.spring.utils.ConnectionUtils"> <property name="dataSource" ref="datasource"></property> </bean> <!--配置事务管理器--> <bean id="transactionManagement" class="com.spring.utils.TransactionManagement"> <property name="connectionUtils" ref="connectionUtils"></property> </bean> </beans>
-
使用事务
说明:每个方法都需要使用,代码比较臃肿,不易维护需要我们进行改造package com.spring.service.impl; import com.spring.dao.AccountDao; import com.spring.entity.Account; import com.spring.entity.Area; import com.spring.service.AccountService; import com.spring.utils.TransactionManagement; /** * 问题:每个方法都写txManagement 事务方法 * 代码比较臃肿,不易维护 */ public class AccountServiceImpl implements AccountService { private AccountDao accountDao; private TransactionManagement txManagement; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void setTxManagement(TransactionManagement txManagement) { this.txManagement = txManagement; } public Account findAccountByName(String accountName) { try{ txManagement.beginTransaction(); Account accountByName = accountDao.findAccountByName(accountName); txManagement.commit(); return accountByName; }catch (Exception e){ txManagement.rollback(); throw new RuntimeException(e); }finally { txManagement.release(); } } public void updateAccount(Account account) { try{ txManagement.beginTransaction(); accountDao.updateAccount(account); txManagement.commit(); }catch (Exception e){ txManagement.rollback(); throw new RuntimeException(e); }finally { txManagement.release(); } } public void transfer(String sourceName, String targetName, Float money) { try{ txManagement.beginTransaction(); //根据A名称查询出账户 Account source = accountDao.findAccountByName(sourceName); //根据B名称查询出账户 Account target = accountDao.findAccountByName(targetName); //转出账户减钱 source.setMoney(source.getMoney() - money); //转入账户加钱 target.setMoney(target.getMoney() + money); //更新转出账户 accountDao.updateAccount(source); int i = 1/0; //更新转入账户 accountDao.updateAccount(target); txManagement.commit(); }catch (Exception e){ txManagement.rollback(); throw new RuntimeException(e); }finally { txManagement.release(); } } }
动态代理
- 概念
* 动态代理
* 特点:字节码随用随创建,随用随加载
* 作用:不修改源码的基础上对方法增强
* 分类:
* 基于接口的动态代理
* 基于类的动态代理
* 基于接口的动态代理:
* 涉及的类:Proxy
* 提供者:JDK官方
* 创建接口代理对象:
* 使用Proxy的newProxyInstance方法
* 创建接口代理的要求:
* 被代理类最少要实现一个接口,如果没有则不能使用。
* newProxyInstance方法的参数。
* ClassLoader:类加载器
* 他是用于加载代理对象字节码的,和被代理对象使用相同的类加载器。固定写法。
* Class[]:字节码数组
* 他是用于让代理对象和被代理对象有相同方法,固定写法。
* InvocationHandler:用于提供增强的代码
* 他是让我们写如何代理,我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的,此接口的实现类都是谁用谁写。
接口代理
public static void main(String[] args) {
final Product product = new Product();
IProduct iProduct = (IProduct)Proxy.newProxyInstance(product.getClass().getClassLoader(), product.getClass().getInterfaces(), new InvocationHandler() {
/**
* 作用:执行被代理对象的任何接口方法都会经过该方法
* @param proxy 代理对象的引用,一般不用
* @param method 当前执行的方法
* @param args 和被代理有相同的返回值
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//提供增强的方法
Object returnValue = null;
//1、获取执行方法的参数
Float arg = (Float) args[0];
//2.判断时不是增强方法(销售)
if("saleProduct".equals(method.getName())){
returnValue = method.invoke(product, arg * 0.8f);
}
return returnValue;
}
});
iProduct.saleProduct(10000);
}
}
-
类的代理
导包<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.1_3</version> </dependency>
* 创建接口代理对象: * Enhancer类中的create方法 * 创建类代理的要求: * 被代理类不是最终类。 最终类指被final修饰的类,不能被修改。 * create方法的参数。 * Class字节码数组 * 他是用于指定被代理对象的字节码。 * * Callback:用于提供增强的代码 * 他是让我们写如何代理。我们一般都是些一个该接口的实现类、通常情况下都是 * 匿名内部类,但是不是必须的。 * 此接口的实现类都是谁用谁写。 * 我们一般写的都是该接口的子接口实现类:MethodInterceptor public static void main(String[] args) { final Product product = new Product(); IProduct p = (IProduct) Enhancer.create(product.getClass(), new MethodInterceptor() { /** * 作用:执行被代理对象的任何接口方法都会经过该方法 * @param proxy 代理对象的引用,一般不用 * @param method 当前执行的方法 * @param args 和被代理有相同的返回值 * @return * @throws Throwable */ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //提供增强的方法 Object returnValue = null; //1、获取执行方法的参数 Float arg = (Float) args[0]; //2.判断时不是增强方法(销售) if ("saleProduct".equals(method.getName())) { returnValue = method.invoke(product, arg * 0.8f); } return returnValue; } }); p.saleProduct(10000f); } }
-
总结:
代理都是向上转型 -
1
-
-
-
git地址:
https://gitee.com/Xiaokeworksveryhard/dynamic_proxy.git