(代码例子)spring基于注解AOP实现事务控制
2019-05-11 16:06
393 查看
pom.xml:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> </dependencies>
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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--配置spring创建容器时要扫描的包--> <context:component-scan base-package="com.itheima"></context:component-scan> <!--配置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="1234"></property> </bean> <!--开启spring对注解AOP的支持--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
ConnectionUtils:
/** * 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定 */ @Component("connectionUtils") public class ConnectionUtils { private ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); @Autowired private 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(); } }
AccountDaoImpl:
/** * 账户的持久层实现类 */ @Repository("accountDao") public class AccountDaoImpl implements IAccountDao { @Autowired private QueryRunner runner; @Autowired private ConnectionUtils connectionUtils; @Override public List<Account> findAllAccount() { try{ return runner.query(connectionUtils.getThreadConnection(),"select * from account",new BeanListHandler<Account>(Account.class)); }catch (Exception e) { throw new RuntimeException(e); } }
....
AccountServiceImpl:
@Service("accountService") public class AccountServiceImpl implements IAccountService{ @Autowired private IAccountDao accountDao; @Override public List<Account> findAllAccount() { return accountDao.findAllAccount(); }
...
@Override public 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); }
...
TransactionManager:
注意:因为分别配置前置通知后置通知会存在顺序问题
1.前置通知2.最终通知释放资源导致连接被回收3.执行方法4.后置通知/异常通知
所以一般会配置环绕通知来解决。
/** * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接 */ @Component("txManager") @Aspect public class TransactionManager { @Autowired private ConnectionUtils connectionUtils; @Pointcut("execution(* com.itheima.service.impl.*.*(..))") private void pt1(){} /** * 开启事务 */ 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(); } } @Around("pt1()") public Object aroundAdvice(ProceedingJoinPoint pjp){ Object rtValue = null; try { //1.获取参数 Object[] args = pjp.getArgs(); //2.开启事务 this.beginTransaction(); //3.执行方法 rtValue = pjp.proceed(args); //4.提交事务 this.commit(); //返回结果 return rtValue; }catch (Throwable e){ //5.回滚事务 this.rollback(); throw new RuntimeException(e); }finally { //6.释放资源 this.release(); } } }
测试类:
/** * 使用Junit单元测试:测试我们的配置 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountServiceTest { @Autowired private IAccountService as; @Test public void testTransfer(){ as.transfer("aaa","bbb",100f); } }
相关文章推荐
- spring AOP + 自定义注解实现权限控制小例子
- spring 基于AOP事务控制实现的基础
- spring AOP + 自定义注解实现权限控制小例子
- Spring学习3—控制反转(IOC)基于Annotation(注解)的依赖注入实现
- 基于纯Java代码的Spring容器和Web容器零配置的思考和实现(1) - 数据源与事务管理
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
- Spring Mvc那点事---(33)Spring事务基于AOP实现
- 基于spring的aop实现读写分离与事务配置
- spring AOP + 自定义注解实现权限控制小例子
- Spring_Spring与AOP_AspectJ基于注解的AOP实现
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
- springAOP与自定义注解实现细粒度权限控制管理
- Spring第八篇【XML、注解实现事务控制】
- Spring AOP基于注解的“零配置”方式实现以及一些其他知识点
- Spring -- tx:annotation-driven 注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别
- 一步一步深入spring(5)--使用基于注解的spring实现 AOP
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。
- 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。