发布于2021-06-14 09:54 阅读(605) 评论(0) 点赞(17) 收藏(0)
maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.10.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
示例代码
package com;
import com.mysql.jdbc.Driver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import java.sql.Connection;
/**
* @author yinyuming
* @date 2021-06-08 11:45
*/
public class SpringTest {
public static void main(String[] args) throws Exception {
//1、初始化数据源
SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource(new Driver(), "jdbc:mysql://127.0.0.1:3306/yymb?useUnicode=true&characterEncoding=utf-8");
simpleDriverDataSource.setPassword("123456");
simpleDriverDataSource.setUsername("root");
//2、初始化事务管理器
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(simpleDriverDataSource);
//开启事务
TransactionStatus transaction = null;
try {
transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
//以下代码块,就可以认为是其他地方获取的连接了,如mybatis等拿到的都是相同的连接
{
//通过DataSourceUtils获取连接
Connection connection1 = DataSourceUtils.getConnection(simpleDriverDataSource);
//通过DataSourceUtils获取连接
Connection connection2 = DataSourceUtils.getConnection(simpleDriverDataSource);
//上下文获取的连接,connection2和connection1获取到的是相同的连接
System.out.println(connection2 == connection1);
}
//关闭事务
transactionManager.commit(transaction);
}catch (Exception ex){
if(transaction !=null){
transactionManager.rollback(transaction);
}
}
}
}
主要核心类org.springframework.transaction.support.ransactionSynchronizationManager存放这ThreadLocal,线程变量,上下文中都是通过该变量获取数据
1、获取上下文连接:TransactionSynchronizationManager.getResource(dataSource)
2、绑定上下文连接:TransactionSynchronizationManager.bindResource(dataSource, txObject.getConnectionHolder());
源码入口:SqlSessionFactoryBean的buildSqlSessionFactory方法
mybatis事务管理接口TransactionFactory,(mybatis初始化DefaultSqlSessionFactory会话工厂就是通过事务工厂获取事务的),通过SpringManagedTransactionFactory事务工厂继承了TransactionFactory接口,所以核心功能就是SpringManagedTransactionFactory这个spring的事务管理入口,该类生成了SpringManagedTransaction事务类,对mybatis获取的事务就是这个类,用于执行sql。
总结:SpringManagedTransactionFactory就是spring扩展mybatis事务类。
private final DataSource dataSource;
private Connection connection;
private boolean isConnectionTransactional;
private boolean autoCommit;
private void openConnection() throws SQLException {
this.connection = DataSourceUtils.getConnection(this.dataSource);
.....省略
}
能看到这个类获取的数据库连接是通过DataSourceUtils获取的,静态方法,通过dataSource中获取连接,然后放到TransactionSynchronizationManager的ThreadLocal线程变量中
这样一个线程中,就可以获取到相同的一个数据库连接了
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
....省略
}
下面是一些核心源码,位置TransactionAspectSupport.invokeWithinTransaction ,aop切入后的方法
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
//开始事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
//回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
....省略
}
源码中最终是用到事务管理器,PlatformTransactionManager这个引用值,我们用DataSourceTransactionManager这个实现类,也是维护和使用TransactionSynchronizationManager的事务的。
所以原理是通过ThreadLocal,拿到上下文的数据库连接,做一些数据库事务的提交和回滚等。
上面讲了连接如何传递上下文的,下面讲一下spring声明式事务的源码流程,核心入口@EnableTransactionManagement
下图参考:https://www.cnblogs.com/dennyzhangdd/p/9602673.html#_label2_0
注解配置一些相关的代理方式,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//proxyTargetClass = false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
boolean proxyTargetClass() default false;
//事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
AdviceMode mode() default AdviceMode.PROXY;
//连接点上有多个通知时,排序,默认最低。值越大优先级越低。
int order() default Ordered.LOWEST_PRECEDENCE;
}
原文链接:https://blog.csdn.net/freshbar/article/details/117781293
作者:想要飞翔的天使
链接:http://www.javaheidong.com/blog/article/222721/4b45eedc0abbd480b6b7/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!