spring-事务阅读笔记

8 篇文章 0 订阅
4 篇文章 0 订阅

再次时隔几个月公司的工作,感觉公司的中间件虽然有点粗糙,但是大佬们会去分享设计思路,这个真的很棒,回头再看代码发现以前的事务草稿里面竟然有好长文章,然而我自己都看不懂,删掉之前的重写。
换一个思路去思考这种框架或者中间件的写法,以前是为了面试/纯粹炫技去读,对我本身的提升并没有多少。从我如何去写一个JDBC的事务去看看问题的发展
事务,原生JDBC就带有了事务,本质上Spring就是将其做了一层封装。然后让它尽可能的无感知给我们去快速开发。那么如果没有JDBC,我应该咋办了。现在把基础的代码撸出来

    public void transferAccounts(String from,String to,double money) {
        //对事务的操作
        Connection con = null;
        try{
            con = JdbcUtils.getConnection();
            con.setAutoCommit(false);
            //增删该查,干了一堆的活
            //提交事务
            con.commit();
        } catch (Exception e) {
            try {
               //异常回滚
                con.rollback();
            } catch (SQLException e1) {
                e.printStackTrace();
            }
            throw new RuntimeException(e);
        }
    }

这上面就的代码就是开启事务,而不是自动提交,干完活就进行提交,出了错就回滚
注解或者xml bean配置的方式,这里就直接使用注解了,因为不外乎一个解析XML,一个读注解生成的文档
@Transactional(rollbackFor = {SQLException.class})
仅仅默认注解,是不会异常回滚。需要加入rollbackFor,才会回滚。
那么异常的回滚机制,在源码分析里面,我们就只需要看这2个点,看一看spring是怎么将jdbc的代码封装,如果从我的思路来说
1.Connection全局变量,如果是原子模式,用hashmap,保证key的唯一性进行存储,保证每个线程可以取对应的连接
2.切入的方式,就easy了,判断属性,然后选择是否切入。
但是Spring还有几个特点,下图是经典的一张图,我看到了不下数百次?然而还是偶尔会忘其中一个
在这里插入图片描述

刚才的代码里面只有回滚规则,spring基于此有事务的其他极大特性,事务超时/是否只读这2个实现都很easy,问题是传播行为,隔离规则,我们需要在代码里面好好看一看。

找到这个解析handler类,

public class TxNamespaceHandler extends NamespaceHandlerSupport {

	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";


	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}


	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}

}

因为我之前配置的annotation-driven,所以看这个是写类怎么解析
解析事务的类入口是AnnotationDrivenBeanDefinitionParser

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        String mode = element.getAttribute("mode");
        if("aspectj".equals(mode)) {
            this.registerTransactionAspect(element, parserContext);
        } else {
            AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
        }

        return null;
    }

后续就是一段解析。解析的bean结构具体为
1.org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
2.TransactionInterceptor.class
3.BeanFactoryTransactionAttributeSourceAdvisor.class

然后具体逻辑就在代理类里,代理走AOP一套
AOPUTILS里面 APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class)
在这里插入图片描述
代理类实在在这里,逻辑是,先查询一次是否有,没有就调用生成。

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if(!this.earlyProxyReferences.contains(cacheKey)) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

    protected Object getCacheKey(Class<?> beanClass, String beanName) {
        return beanClass.getName() + "_" + beanName;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if(beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if(!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if(specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

代理类已经生成,然后找切面。这里都是统一解决完代理类,然后再进行具体的advisor进行织入,逻辑还是基础的。

 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
        List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        this.extendAdvisors(eligibleAdvisors);
        if(!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
        }

        return eligibleAdvisors;
    }

找到相关的adivsor类(因为这里是AbstractAdvisorAutoProxyCreator个类实现类,在AOP的时候是有4个实现的,其实也就是容器化了。),然后进行一一匹配
1.找到容器实现的advisor接口
2.然后进行匹配,判断advisor是不是IntroductionAdvisor,不是就判断是不是PointcutAdvisor
3.其他返回true
debug的时候可以明显的看到PonitCut内容
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor$1: org.springframework.transaction.annotation.AnnotationTransactionAttributeSource@3012646b
也就是BeanFactoryTransactionAttributeSourceAdvisor
在这里插入图片描述
非静态变量的pointcut,使用的是TransactionAttributeSourcePointcut
主要是使用match方法,match方法又是封装在AOPUTILS.canApply来解决。
然后在动态代理里面,其实就是
遍历所有使用的 Advisor,获得其Advice,将Advice转为MethodInterceptor。
在事务里面也就是开始几个基础bean容器中的TransactionInterceptor类

在这里插入图片描述
具体的事务逻辑就在transactionAspectSupport

 protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
        //获取事务配置
        final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        //事务管理器判断是否开启
        final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
        //切入点名定义
        final String joinpointIdentification = this.methodIdentification(method, targetClass);
        if(txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
           //.....
        } else {
            //开启事务
            TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                retVal = invocation.proceedWithInvocation();
            } catch (Throwable var15) {
                this.completeTransactionAfterThrowing(txInfo, var15);
                throw var15;
            } finally {
                this.cleanupTransactionInfo(txInfo);
            }

            this.commitTransactionAfterReturning(txInfo);
            return retVal;
        }
    }
   protected TransactionAspectSupport.TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
        
        TransactionStatus status = null;
        if(txAttr != null) {
            if(tm != null) {
                 //获得事务
                status = tm.getTransaction((TransactionDefinition)txAttr);
            } else if(this.logger.isDebugEnabled()) {
                this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");
            }
        }

        return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
    }

最下面的获取代码如下,是一个threadlocal来判断当前线程事务的获取

 private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal("Transactional resources");
 private static Object doGetResource(Object actualKey) {
        Map<Object, Object> map = (Map)resources.get();
        if(map == null) {
            return null;
        } else {
            Object value = map.get(actualKey);
            if(value instanceof ResourceHolder && ((ResourceHolder)value).isVoid()) {
                map.remove(actualKey);
                if(map.isEmpty()) {
                    resources.remove();
                }

                value = null;
            }

            return value;
        }
    }
 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        Object transaction = this.doGetTransaction();
        boolean debugEnabled = this.logger.isDebugEnabled();
        if(definition == null) {
            definition = new DefaultTransactionDefinition();
        }

        if(this.isExistingTransaction(transaction)) {
            //事务的传播性
            return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
        } else if(((TransactionDefinition)definition).getTimeout() < -1) {
            throw new InvalidTimeoutException("Invalid transaction timeout", ((TransactionDefinition)definition).getTimeout());
        } else if(((TransactionDefinition)definition).getPropagationBehavior() == 2) {
            throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
        } else if(((TransactionDefinition)definition).getPropagationBehavior() != 0 && ((TransactionDefinition)definition).getPropagationBehavior() != 3 && ((TransactionDefinition)definition).getPropagationBehavior() != 6) {
            boolean newSynchronization = this.getTransactionSynchronization() == 0;
            return this.prepareTransactionStatus((TransactionDefinition)definition, (Object)null, true, newSynchronization, debugEnabled, (Object)null);
        } else {
            AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources = this.suspend((Object)null);
            if(debugEnabled) {
                this.logger.debug("Creating new transaction with name [" + ((TransactionDefinition)definition).getName() + "]: " + definition);
            }

            try {
                boolean newSynchronization = this.getTransactionSynchronization() != 2;
                DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                this.doBegin(transaction, (TransactionDefinition)definition);
                this.prepareSynchronization(status, (TransactionDefinition)definition);
                return status;
            } catch (RuntimeException var7) {
                this.resume((Object)null, suspendedResources);
                throw var7;
            } catch (Error var8) {
                this.resume((Object)null, suspendedResources);
                throw var8;
            }
        }
    }

PROPAGATION_NOT_SUPPORTED 事务逻辑可以看到

 if(definition.getPropagationBehavior() == 4) {
                if(debugEnabled) {
                    this.logger.debug("Suspending current transaction");
                }
				//在这里将事务从原本线程进行移除,然后进行再新建
                suspendedResources = this.suspend(transaction);
                newSynchronization = this.getTransactionSynchronization() == 0;
                return this.prepareTransactionStatus(definition, (Object)null, false, newSynchronization, debugEnabled, suspendedResources);
            }else  if(definition.getPropagationBehavior() == 3) {
                //..
                   DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                    this.doBegin(transaction, definition);
                    this.prepareSynchronization(status, definition).
                //..
            }

整个事务创建的使用是DataSourceTransactionManager
doBegin来创建

protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
        Connection con = null;
        try {
            if(txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.getConnection();
                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }
            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
             //获得连接
            con = txObject.getConnectionHolder().getConnection();
             //设置是否只读和隔离级别
            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);
            if(con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }

                con.setAutoCommit(false);
            }

            txObject.getConnectionHolder().setTransactionActive(true);
            int timeout = this.determineTimeout(definition);
            if(timeout != -1) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }
            if(txObject.isNewConnectionHolder()) {
                 //和线程进行绑定
                TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());
            }
        } catch (Throwable var7) {
            if(txObject.isNewConnectionHolder()) {
                DataSourceUtils.releaseConnection(con, this.dataSource);
                txObject.setConnectionHolder((ConnectionHolder)null, false);
            }

            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
        }
    }

其他的方法也是最终调用的该类的其他方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值