事务是你们用的最多的,也是比较关心的一个功能。本章就详细讲解spring-tx模块中事务的实现与spring-boot事务的处理。可能这一节就会把spring-tx说完,事务没有你们想象的那么复杂。java
java的链接池,事务管理,持久层(MyBtais,hibernation)都是基于jdbc(Java DataBase Connectivity,java数据库链接)进行演进的。那么仔细看下下面的jdbc代码,从而理解链接池,事务管理,持久层(MyBtais,hibernation)。mysql
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Random; public class Demo { public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; try { Class.forName("com.mysql.jdbc.Driver");// 1. 注册驱动 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","mysql"); // 2. 建立链接 con.setAutoCommit(false);// 3. 不自动提交,开始事务 conn.setReadOnly(true);// 4. 设定只读,或者其余链接设定 String sql = "insert into t_user(userName,pwd)values(?,?)"; // 须要执行的sql语句 ps = conn.prepareStatement( sql );// 5. 在不一样的statement中设置须要执行的sql语句 ps.setObject(1, "小高" + i);// 6. 预编译,参数设置 ps.setObject(2, "123"); ps.execute(); // 7. 执行语句 // 8. 若是是查询插座,对查询结果进行操做 con.commit(); // 9. 提交 } catch (ClassNotFoundException e) { con.rollback(); // 9, 回滚 e.printStackTrace(); } catch (SQLException e) { con.rollback(); // 9. 回滚 e.printStackTrace(); } finally{ try { if (ps!=null) { ps.close(); // 10. 资源释放 } } catch (SQLException e) { e.printStackTrace(); } try { if (conn!=null) { conn.close(); // 10. 资源释放 } } catch (SQLException e) { e.printStackTrace(); } } } }
链接池 | 事务管理器 | 持久 | |
---|---|---|---|
1 | 注册驱动 | ||
2 | 建立链接 | ||
3 | 不自动提交,开始事务 | ||
4 | 设定只读,或者其余链接设定 | ||
5 | 在不一样的statement中设置须要执行的sql语句 | ||
6 | 预编译,参数设置 | ||
7 | 执行语句 | ||
8 | 若是是查询操做,对查询结果进行操做 | ||
9 | 提交或者回滚 | ||
10 | 资源释放 | 资源释放 |
// 时序图spring
<! ------------------------- 无情分割线 --------------------------------------------------->sql
下面声明了TransactionStatus的接口, 实现了TransactionStatus的抽象类AbstractTransactionStatus,还有AbstractTransactionStatus的子类DefaultTransactionStatus与内部类TransactionInfo,其实只须要TransactionInfo一个类就好了,上面几个类的细节不讲述了。数据库
为何spring-tx须要设计那么多类了。其实就是为了实现spring中一个很鸡肋的功能,事务传播功能。为了实现事务传播功能的设计,代码还有不少,本人很是不喜欢这个功能,因此不会讲述事务传播的细节,若是有读者想了解,能够依据本接内容为基本自行扩展。 为何spring-tx须要设计那么多类了。其实就是为了实现spring中一个很鸡肋的功能,事务传播功能。为了实现事务传播功能的设计,代码还有不少,本人很是不喜欢这个功能,因此不会讲述事务传播的细节,若是有读者想了解,能够依据本接内容为基本自行扩展。 为何spring-tx须要设计那么多类了。其实就是为了实现spring中一个很鸡肋的功能,事务传播功能。为了实现事务传播功能的设计,代码还有不少,本人很是不喜欢这个功能,因此不会讲述事务传播的细节,若是有读者想了解,能够依据本接内容为基本自行扩展。mybatis
public abstract class AbstractTransactionStatus implements TransactionStatus { private boolean rollbackOnly = false; private boolean completed = false; @Nullable private Object savepoint }
public class DefaultTransactionStatus extends AbstractTransactionStatus { @Nullable private final Object transaction; private final boolean newTransaction; private final boolean newSynchronization; private final boolean readOnly; private final boolean debug; @Nullable private final Object suspendedResources; }
protected final class TransactionInfo { @Nullable private final PlatformTransactionManager transactionManager; @Nullable private final TransactionAttribute transactionAttribute; private final String joinpointIdentification; @Nullable private TransactionStatus transactionStatus; @Nullable private TransactionInfo oldTransactionInfo; }
<! ------------------------- 无情分割线结束 --------------------------------------------------->框架
spring事务的核心体系是PlatformTransactionManager以及实现了DataSourceTransactionManager(数据源事务管理器,好比mybatis,spring-jdbc),JpaTransactionManager(Jpa事务管理器),HibernateTransactionManager(hibernate5事务管理器)。本节直接讲解DataSourceTransactionManager,其余的管理器使用场景很是少不作讲解了。dom
public interface PlatformTransactionManager { TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
看下这个方法的调用流程,就很容易懂了。一些其余的代码就不要看了,基本是为了jta作了准备
分布式
TransactionInterceptor 只作了一件事情调用了父类TransactionAspectSupport的invokeWithinTransaction方法,那么你们把注意力放到TransactionAspectSupport的invokeWithinTransaction方法上吧ide
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { // PlatformTransactionManager 事务管理 public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) { setTransactionManager(ptm); setTransactionAttributeSource(tas); } @Override public Object invoke(final MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } }); } }
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // 获得对象与方法上的Transactio注解 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); // 获得事务管理器,@Transactio注解变量transactionManager,能够指定这个事务由那个事务管理器执行。 final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { //开启事务 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // 执行方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // 回滚 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 清理TransactionInfo cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; } else { ...... } } protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) { // 若是 条件成立,返回默认事务管理器 if (txAttr == null || this.beanFactory == null) { return getTransactionManager(); } // 得到 事务管理器的名字 String qualifier = txAttr.getQualifier(); // 若是有 if (StringUtils.hasText(qualifier)) { // 经过事务管理器的名字得到事务管理器, return determineQualifiedTransactionManager(qualifier); } else if (StringUtils.hasText(this.transactionManagerBeanName)) { // 默认管理器名字得到管理器 return determineQualifiedTransactionManager(this.transactionManagerBeanName); } else { // 得到默认管理器 PlatformTransactionManager defaultTransactionManager = getTransactionManager(); if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } return defaultTransactionManager; } } // 经过事务管理器的名字得到事务管理器 private PlatformTransactionManager determineQualifiedTransactionManager(String qualifier) { PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier); if (txManager == null) { txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType( this.beanFactory, PlatformTransactionManager.class, qualifier); this.transactionManagerCache.putIfAbsent(qualifier, txManager); } return txManager; }
spring-boot启动事务很简单只须要EnableTransactionManagement注解或者TransactionManagementConfigurationSelector被ApplicationContext加载,那么就会自动启动事务。详细请看下面的流程
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { // 建立Advisor BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); // 建立 注解识别 advisor.setTransactionAttributeSource(transactionAttributeSource()); // 建立方法拦截器与处理器 advisor.setAdvice(transactionInterceptor()); advisor.setOrder(this.enableTx.<Integer>getNumber("order")); return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
事务真的很简单,可是为了作不少的兼容于扩展,spring-tx写得很复杂。我的感受在分布式的微服务框架设计下,不少都不该该要了。