c语言sscanf函数的用法是什么
265
2022-09-23
Spring-tx-TransactionInterceptor类
关于TransactionInterceptor类的解析,将是对spring-tx模块最重要的解析,该类是spring事务模块核心框架代码
TransactionInterceptor继承了TransactionAspectSupport类,所以有一个较为重要的静态方法,该方法由ThreadLocal实现,所以在任何地方都可以获取当前线程的TransactionStatus
public static TransactionStatus currentTransactionStatus()
第一步:首先,有一个类,类的全限定名是org.springframework.aop.framework.CglibAopProxy,而该类里面有一个内部类,是CglibMethodInvocation,该内部类签名如下
private static class CglibMethodInvocation
这个内部类继承了ReflectiveMethodInvocation,但是这个内部是私有的,且该类是spring-tx模块至关重要的类,为了阐述spring-tx,要用到这个类,为此,需要我们自己新建一个类,并且将内部类CglibMethodInvocation的代码,全部都复制出来,将其修饰符改成public,方便我们自己使用,代码如下
.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.UndeclaredThrowableException;import java.util.List;import org.springframework.aop.framework.ReflectiveMethodInvocation;import org.springframework.aop.support.AopUtils;import org.springframework.cglib.proxy.MethodProxy;import org.springframework.lang.Nullable;import org.springframework.util.ReflectionUtils;/** * 这个类与CglibAopProxy.CglibMethodInvocation类内容完全一模一样 * 只不过修饰符是public,为了方便我自己使用 */public class MysCglibMethodInvocation extends ReflectiveMethodInvocation { @Nullable private final MethodProxy methodProxy; public MysCglibMethodInvocation(Object proxy, @Nullable Object target, Method method, Object[] arguments, @Nullable Class> targetClass, List
import java.lang.reflect.Method;import java.util.ArrayList;import javax.sql.DataSource;import org.aopalliance.intercept.MethodInvocation;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;import org.springframework.transaction.annotation.Transactional;import org.springframework.transaction.interceptor.TransactionInterceptor;import com.zaxxer.hikari.HikariDataSource;public class TransactionInterceptorTestMain { public static DataSource dataSource; static { HikariDataSource ds = new HikariDataSource(); // 设置数据库名称,不要忘记修改这个地方 ds.setJdbcUrl("jdbc:mysql://localhost:3306/swttest?serverTimezone=UTC&&useSSL=false"); ds.setUsername("root"); ds.setPassword("123456"); dataSource = ds; } // 能看到这个文章的对这个注解肯定熟悉,别忘了加上就行 @Transactional(rollbackFor = Exception.class) public void create() { JdbcTemplate jdbc = new JdbcTemplate(); jdbc.setDataSource(dataSource); // 执行sql语句,我在数据库中的表名叫t1,里面只有两个字段 jdbc.update("insert into t1 values ('1','上班好困')"); // 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚 // 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚 // 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚 // throw new RuntimeException("MYS"); } public static void main(String[] args) throws Throwable { TransactionInterceptor ti = new TransactionInterceptor(); ti.setTransactionManager(new DataSourceTransactionManager(dataSource)); ti.setTransactionAttributeSource(new AnnotationTransactionAttributeSource()); TransactionInterceptorTestMain obj = new TransactionInterceptorTestMain(); Method createMethod = TransactionInterceptorTestMain.class.getMethod("create"); MethodInvocation mi = new MysCglibMethodInvocation(null, obj, createMethod, null, null, new ArrayList<>(), null); ti.invoke(mi); }}
步骤2和3在相应的链接中我已经阐述过,本文着重分析步骤4
下面是TransactionAspectSupport.invokeWithinTransaction方法的代码片段
// 创建事务TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal = null;try { //执行我们的方法,本文中的create方法用来插入数据 retVal = invocation.proceedWithInvocation();}catch (Throwable ex) { // 如果create方法出异常则代码到这里,并执行回滚 completeTransactionAfterThrowing(txInfo, ex); throw ex;}finally { // 清空当前线程变量里的事务信息 cleanupTransactionInfo(txInfo);}// 提交事务commitTransactionAfterReturning(txInfo);
一:createTransactionIfNecessary 该方法主要使用了DataSourceTransactionManager对象的相关方法开启一个事务,其本质上使用了JDBC的Connection.setAutoCommit,最终返回TransactionInfo,所以我将创建事务的细节都挪到此处讲解,以便于更好理解DataSourceTransactionManager类,理解了这个类,就知道spring是开启一个事务的了
TODO 文章尚未完成,2021年1月18日 09:22:08
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~