事务:通过接口的动态代理加强AccountService 实现转账的事务
ApplicationContext.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/beans http://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.hdh.factory.BeanFactory"> <!-- 注入service --> <property name="as" ref="accountService"></property> <!-- 注入事务管理器 --> <property name="tm" ref="txManager"></property> </bean> <!--配置service --> <bean id="accountService" class="com.hdh.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置dao --> <bean id="accountDao" class="com.hdh.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> <!-- 配置Connection的工具类 ConnectionUtils --> <bean id="connectionUtils" class="com.hdh.utils.ConnectionUtils"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"></property> </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/spring"></property> <property name="user" value="root"></property> <property name="password" value="12345"></property> </bean> <!-- 配置事务管理器--> <bean id="txManager" class="com.hdh.utils.TransactionManager"> <!-- 注入ConnectionUtils --> <property name="connectionUtils" ref="connectionUtils"></property> </bean> </beans>
2.ConnectionUtils.java //获取当前线程上的连接
/** * 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定 */ 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(); } }
3.TranscationManager.java
/** * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接 */ 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(); } } }
4.接口的动态代理加强AccountService
/** * 用于创建Service的代理对象的工厂 */ public class BeanFactory { private AccountService as; private TransactionManager tm; public void setAs(AccountService as) { this.as = as; } public void setTm(TransactionManager tm) { this.tm = tm; } public AccountService getAccountService() { return (AccountService) Proxy.newProxyInstance(as.getClass().getClassLoader(), as.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object invoke=null; try { // 开启事物 tm.beginTransaction(); invoke = method.invoke(as, args); //事务提交 tm.commit(); } catch (Exception e) { // 事物回滚 tm.rollback(); } finally { // 释放连接 tm.release(); } return invoke; } }); } }