本文共 11304 字,大约阅读时间需要 37 分钟。
先结合源码部分看一下执行流程,然后说一下解决方案(本列使用cglib代理,jdk动态代理类似)
话不多说,先看一下代理拦截器方法:public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null;//这是咱们的目标类被各种切面封装后的代理对象 boolean setProxyContext = false; Object target = null; TargetSource targetSource = this.advised.getTargetSource(); try { if (this.advised.exposeProxy) {//很重要,设置了暴露代理才会执行下一步内容 // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy);//设置代理,并保存旧代理(1) setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool... target = targetSource.getTarget(); Class targetClass = (target != null ? target.getClass() : null); List
进一步解析(1)处的内容:
public final class AopContext { //使用threadlocal存储代理对象 private static final ThreadLocal
通过上面的源码分析,
1.开启暴露代理 2.我们可以直接通过AopContext 获取到Proxy对象,从而调用上面被各种切面织入的方法,进而实现代理. 理论不如实践,进行一下对比springboot环境: 开启暴露代理:@EnableAspectJAutoProxy(exposeProxy = true)这一部分是事务不生效实例:
@Servicepublic class TranService{ @Autowired private TranDao tranDao; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void add() { User aaa = new User(); aaa.setAge(22); aaa.setCtime(new Date()); aaa.setUserId(2); aaa.setUserName("aaa"); tranDao.save(aaa); try { b(); }catch (Exception e){ e.printStackTrace(); } } @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class) public void b() { User aaa = new User(); aaa.setAge(33); aaa.setCtime(new Date()); aaa.setUserId(3); aaa.setUserName("bbb"); tranDao.save(aaa); throw new RuntimeException("111"); }}
说明一下上面的代码:按spring事务的规则,调用add()方法士应该开启一个事务,然后b()也加了事务,推断出想在b()调用时,开启单独事务,那么期望结果是a()提交,b()回滚
2019-07-17 21:26:04.623 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.demotran.tran.TranService.add]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Throwable2019-07-17 21:26:04.623 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(76567159)] for JPA transaction2019-07-17 21:26:04.623 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@255421fa]2019-07-17 21:26:04.639 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(76567159 )] for JPA transaction2019-07-17 21:26:04.639 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Participating in existing transactionHibernate: select user0_.user_id as user_id1_0_0_, user0_.age as age2_0_0_, user0_.ctime as ctime3_0_0_, user0_.user_name as user_nam4_0_0_ from t_user user0_ where user0_.user_id=?2019-07-17 21:26:04.717 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(76567159 )] for JPA transaction2019-07-17 21:26:04.717 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Participating in existing transactionHibernate: select user0_.user_id as user_id1_0_0_, user0_.age as age2_0_0_, user0_.ctime as ctime3_0_0_, user0_.user_name as user_nam4_0_0_ from t_user user0_ where user0_.user_id=?java.lang.RuntimeException: 111 at com.example.demotran.tran.TranService.b(TranService.java:42) ......2019-07-17 21:26:04.717 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit2019-07-17 21:26:04.717 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(76567159 )]//两条数据都进行了插入,没有回滚Hibernate: insert into t_user (age, ctime, user_name, user_id) values (?, ?, ?, ?)Hibernate: insert into t_user (age, ctime, user_name, user_id) values (?, ?, ?, ?)2019-07-17 21:26:04.733 DEBUG 7976 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(76567159 )] after transaction
看一下符合期望的编码:
package com.example.demotran.tran;import org.springframework.aop.framework.AopContext;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import java.util.Date;@Servicepublic class TranService{ @Autowired private TranDao tranDao; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void add() { User aaa = new User(); aaa.setAge(22); aaa.setCtime(new Date()); aaa.setUserId(2); aaa.setUserName("aaa"); tranDao.save(aaa); try { TranService tranService = (TranService) AopContext.currentProxy(); tranService.b(); }catch (Exception e){ e.printStackTrace(); } } @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class) public void b() { User aaa = new User(); aaa.setAge(33); aaa.setCtime(new Date()); aaa.setUserId(3); aaa.setUserName("bbb"); tranDao.save(aaa); throw new RuntimeException("111"); }}
看一下执行日志:
//开启事务2019-07-17 21:28:34.108 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.demotran.tran.TranService.add]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Throwable2019-07-17 21:28:34.108 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(176172822)] for JPA transaction2019-07-17 21:28:34.124 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@58c34766]2019-07-17 21:28:34.124 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(176172822 )] for JPA transaction2019-07-17 21:28:34.124 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Participating in existing transactionHibernate: select user0_.user_id as user_id1_0_0_, user0_.age as age2_0_0_, user0_.ctime as ctime3_0_0_, user0_.user_name as user_nam4_0_0_ from t_user user0_ where user0_.user_id=?2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(176172822 )] for JPA transaction//挂起了当前事务2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Suspending current transaction, creating new transaction with name [com.example.demotran.tran.TranService.b]//开启了一个新的实体管理器为事务操作2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(1157613382 )] for JPA transaction2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1e1d8bf4]2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1157613382 )] for JPA transaction2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Participating in existing transactionHibernate: select user0_.user_id as user_id1_0_0_, user0_.age as age2_0_0_, user0_.ctime as ctime3_0_0_, user0_.user_name as user_nam4_0_0_ from t_user user0_ where user0_.user_id=?2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Initiating transaction rollback//回滚了事务2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Rolling back JPA transaction on EntityManager [SessionImpl(1157613382 )]2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(1157613382 )] after transaction//重启了当前事务2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Resuming suspended transaction after completion of inner transactionjava.lang.RuntimeException: 111 at com.example.demotran.tran.TranService.b(TranService.java:41) ......2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit2019-07-17 21:28:34.170 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(176172822 )]//最终只有一条数据插入库中Hibernate: insert into t_user (age, ctime, user_name, user_id) values (?, ?, ?, ?)2019-07-17 21:28:34.186 DEBUG 7940 --- [ restartedMain] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(176172822 )] after transaction
好了,今天就到这里.如果你有更好的方法,敬请留言,相互学习.
转载地址:http://uduti.baihongyu.com/