zoukankan      html  css  js  c++  java
  • spring源码解析--事务篇(前篇)

     对于每一个JAVA程序员,spring应该是再熟悉不过的框架了,它的功能有多强大我就不多说了,既然他有这么强大的功能,是如何实现的呢?这个就需要从他的原理去了解,而最直接了解原理的方式莫过于源码。当然Spring源码那么大,有时候会显得无从下手,而且也是晦涩难懂。所以我们可以按照功能模块地方式去解读,第一阶段我就先跟大家分享下面spring的事务,读源码前,我们先得了解下spring事务的相关原理:事务的传播特性和隔离级别

      spring的传播特性: PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY, PROPAGATION_REQUIRES_NEW, PROPAGATION_NOT_SUPPORTED, PROPAGATION_NEVER, PROPAGATION_NESTED

      我们来一一介绍下

    复制代码
        class A{
            methodA(){
                //逻辑处理
                b.methodB();
                //逻辑处理
            }
        }
        class B{
            methodB();
        }
    复制代码

      1.PROPAGATION_REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启

      解释:当A.methodA()和B.methodB()都打上REQUIRED的事务标志,执行A.methodA()方法的时候,看到上下文没有事务,会新建一个事务,当执行到b.methodB()的时候,发现上下文已经有事务了,则不会新建事务,用A.methodA()新建的那个事务。

      如果b.methodB()执行成功,a.methodA()执行失败,那么b.methodB()和a.methodA()都会回滚(用的都是a.methodA()的事务)

      2.PROPAGATION_SUPPORTS:如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

      解释:当B.methodB()打上PROPAGATION_SUPPORTS的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则b.methodB()沿用该事务,反之b.methodB()就以非事物的方式执行

      3.PROPAGATION_MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常

      解释:当B.methodB()打上PROPAGATION_MANDATORY的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则b.methodB()沿用该事务,如果没有,则会抛出异常

      4.PROPAGATION_REQUIRES_NEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起

      解释:当B.methodB()打上PROPAGATION_REQUIRES_NEW的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则会挂起A.methodA()的事务,新建一个属于b.methodB(),当b.methodB()

      的事务执行结束的时候,则会唤醒b.methodB()的事务。和PROPAGATION_REQUIRED的差别在于回滚,当b.methodB()的事务提交后,A.methodA()执行失败,只会回滚A.methodA不会回滚b.methodB(),当b.methodB()执行失败,异常被A.methodA()方法   

       catch到的话,A.methodA()事务不会回滚

      5.PROPAGATION_NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务

      解释:当B.methodB()打上PROPAGATION_NOT_SUPPORTED的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果A.methodA()有事务,则会挂起A.methodA()的事务,当执行完b.methodB()方法的时候,             A.methodA()方法继续以事务的方式执行

      6.PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常

      解释:当B.methodB()打上PROPAGATION_NEVER的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,会检查上下文有没有事务,如果有事务,则抛出异常,如果没有则以非事务执行

      7.PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, PROPAGATION_REQUIRED 属性执行

      解释:当B.methodB()打上PROPAGATION_NOT_SUPPORTED的事务标志,执行A.methodA()方法,当执行到b.methodB()的时候,如果A.methodA()方法有事务,则会用当前事务,如果 b.methodB()执行失败,只会回滚  b.methodB(),不会回滚A.methodA(),   只有当A.methodA()执行完成后才会提交b.methodB()的事务,如果A.methodA()方法没有事务,就会新建一个事务;

      事务隔离级别:  ISOLATION_DEFAULT,ISOLATION_READ_UNCOMMITTED,ISOLATION_READ_COMMITTED,ISOLATION_REPEATABLE_READ,ISOLATION_SERIALIZABLE 

      1.ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别   

      2. ISOLATION_READ_UNCOMMITTED :这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 

      3. ISOLATION_READ_COMMITTED  :保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。:

      4. ISOLATION_REPEATABLE_READ  :这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。 

      5. ISOLATION_SERIALIZABLE :这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。

      ok,现在我们事务的传播特性和隔离级别有了一定的了解。我们开始去尝试阅读源码

      想要阅读源码,我们必须先弄清楚spring事务的几个类和接口的关系,先看下图:

      

      事务的定义接口:TransactionDefinition 

      包含事务的两个重要属性:传播特性和隔离级别(上面已作介绍,不在重复)

    复制代码
    public interface TransactionDefinition {
        int PROPAGATION_REQUIRED = 0;
        int PROPAGATION_SUPPORTS = 1;
        int PROPAGATION_MANDATORY = 2;
        int PROPAGATION_REQUIRES_NEW = 3;
        int PROPAGATION_NOT_SUPPORTED = 4;
        int PROPAGATION_NEVER = 5;
        int PROPAGATION_NESTED = 6;
        int ISOLATION_DEFAULT = -1;
        int ISOLATION_READ_UNCOMMITTED = 1;
        int ISOLATION_READ_COMMITTED = 2;
        int ISOLATION_REPEATABLE_READ = 4;
        int ISOLATION_SERIALIZABLE = 8;
        int TIMEOUT_DEFAULT = -1;
    
        int getPropagationBehavior();
    
        int getIsolationLevel();
    
        int getTimeout();
    
        boolean isReadOnly();
    
        String getName();
    }
    复制代码

       TransactionDefinition 的一个实现类:DefaultTransactionDefinition

      就是对上述属性设置一些默认值,默认的传播特性为PROPAGATION_REQUIRED ,隔离级别为ISOLATION_DEFAULT 

    复制代码
    public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
        public static final String PREFIX_PROPAGATION = "PROPAGATION_";
        public static final String PREFIX_ISOLATION = "ISOLATION_";
        public static final String PREFIX_TIMEOUT = "timeout_";
        public static final String READ_ONLY_MARKER = "readOnly";
        static final Constants constants = new Constants(TransactionDefinition.class);
        private int propagationBehavior = 0;//默认值
        private int isolationLevel = -1;
        private int timeout = -1;
        private boolean readOnly = false;
        private String name;
    
        public DefaultTransactionDefinition() {
        }
    
        public DefaultTransactionDefinition(TransactionDefinition other) {
            this.propagationBehavior = other.getPropagationBehavior();
            this.isolationLevel = other.getIsolationLevel();
            this.timeout = other.getTimeout();
            this.readOnly = other.isReadOnly();
            this.name = other.getName();
        }
    
        public DefaultTransactionDefinition(int propagationBehavior) {
            this.propagationBehavior = propagationBehavior;
        }
    
        public final void setPropagationBehaviorName(String constantName) throws IllegalArgumentException {
            if(constantName != null && constantName.startsWith("PROPAGATION_")) {
                this.setPropagationBehavior(constants.asNumber(constantName).intValue());
            } else {
                throw new IllegalArgumentException("Only propagation constants allowed");
            }
        }
    
        public final void setPropagationBehavior(int propagationBehavior) {
            if(!constants.getValues("PROPAGATION_").contains(Integer.valueOf(propagationBehavior))) {
                throw new IllegalArgumentException("Only values of propagation constants allowed");
            } else {
                this.propagationBehavior = propagationBehavior;
            }
        }
    
        public final int getPropagationBehavior() {
            return this.propagationBehavior;
        }
    
        public final void setIsolationLevelName(String constantName) throws IllegalArgumentException {
            if(constantName != null && constantName.startsWith("ISOLATION_")) {
                this.setIsolationLevel(constants.asNumber(constantName).intValue());
            } else {
                throw new IllegalArgumentException("Only isolation constants allowed");
            }
        }
    
        public final void setIsolationLevel(int isolationLevel) {
            if(!constants.getValues("ISOLATION_").contains(Integer.valueOf(isolationLevel))) {
                throw new IllegalArgumentException("Only values of isolation constants allowed");
            } else {
                this.isolationLevel = isolationLevel;
            }
        }
    
        public final int getIsolationLevel() {
            return this.isolationLevel;
        }
    
        public final void setTimeout(int timeout) {
            if(timeout < -1) {
                throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT");
            } else {
                this.timeout = timeout;
            }
        }
    
        public final int getTimeout() {
            return this.timeout;
        }
    
        public final void setReadOnly(boolean readOnly) {
            this.readOnly = readOnly;
        }
    
        public final boolean isReadOnly() {
            return this.readOnly;
        }
    
        public final void setName(String name) {
            this.name = name;
        }
    
        public final String getName() {
            return this.name;
        }
    
        public boolean equals(Object other) {
            return other instanceof TransactionDefinition && this.toString().equals(other.toString());
        }
    
        public int hashCode() {
            return this.toString().hashCode();
        }
    
        public String toString() {
            return this.getDefinitionDescription().toString();
        }
    
        protected final StringBuilder getDefinitionDescription() {
            StringBuilder result = new StringBuilder();
            result.append(constants.toCode(Integer.valueOf(this.propagationBehavior), "PROPAGATION_"));
            result.append(',');
            result.append(constants.toCode(Integer.valueOf(this.isolationLevel), "ISOLATION_"));
            if(this.timeout != -1) {
                result.append(',');
                result.append("timeout_").append(this.timeout);
            }
    
            if(this.readOnly) {
                result.append(',');
                result.append("readOnly");
            }
    
            return result;
        }
    }
    复制代码

        TransactionAttribute接口

     定义对什么类型的异常进行回滚

    public interface TransactionAttribute extends TransactionDefinition {
        String getQualifier();
    
        boolean rollbackOn(Throwable var1);
    }

      TransactionAttribute的实现类:DefaultTransactionAttribute

     指明了默认对RuntimeException 和Error都进行回滚

    复制代码
    public class DefaultTransactionAttribute extends DefaultTransactionDefinition implements TransactionAttribute {
        private String qualifier;
    
        public DefaultTransactionAttribute() {
        }
    
        public DefaultTransactionAttribute(TransactionAttribute other) {
            super(other);
        }
    
        public DefaultTransactionAttribute(int propagationBehavior) {
            super(propagationBehavior);
        }
    
        public void setQualifier(String qualifier) {
            this.qualifier = qualifier;
        }
    
        public String getQualifier() {
            return this.qualifier;
        }
    
        public boolean rollbackOn(Throwable ex) {//指明了对RuntimeException 和Error进行回滚
            return ex instanceof RuntimeException || ex instanceof Error;
        }
    
        protected final StringBuilder getAttributeDescription() {
            StringBuilder result = this.getDefinitionDescription();
            if(this.qualifier != null) {
                result.append("; '").append(this.qualifier).append("'");
            }
    
            return result;
        }
    }

    复制代码

       事务模板类TransactionTemplate

       他的核心是里面有PlatformTransactionManager 这个事务管理类,用它来对事务提交和回滚。我们的业务逻辑只要写在TransactionCallback.doInTransaction()方法里面既可以,每次执行这个方法前,先会transactionManager.getTransaction(this)开启一   个事务,执行TransactionCallback.doInTransaction()异常的话会调用transactionManager.rollback(status)来回滚事务,正确的话就会调用transactionManager.commit(status)提交事务;

    复制代码
    public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
        protected final Log logger = LogFactory.getLog(this.getClass());
        private PlatformTransactionManager transactionManager;
    
        public TransactionTemplate() {
        }
    
        public TransactionTemplate(PlatformTransactionManager transactionManager) {
            this.transactionManager = transactionManager;
        }
    
        public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
            super(transactionDefinition);
            this.transactionManager = transactionManager;
        }
    
        public void setTransactionManager(PlatformTransactionManager transactionManager) {
            this.transactionManager = transactionManager;
        }
    
        public PlatformTransactionManager getTransactionManager() {
            return this.transactionManager;
        }
    
        public void afterPropertiesSet() {
            if(this.transactionManager == null) {
                throw new IllegalArgumentException("Property 'transactionManager' is required");
            }
        }
    
        public <T> T execute(TransactionCallback<T> action) throws TransactionException {
            if(this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
                return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);
            } else {
                TransactionStatus status = this.transactionManager.getTransaction(this);
    
                Object result;
                try {
                    result = action.doInTransaction(status);//业务逻辑代码写在这里
                } catch (RuntimeException var5) {
                    this.rollbackOnException(status, var5);
                    throw var5;
                } catch (Error var6) {
                    this.rollbackOnException(status, var6);
                    throw var6;
                } catch (Exception var7) {
                    this.rollbackOnException(status, var7);
                    throw new UndeclaredThrowableException(var7, "TransactionCallback threw undeclared checked exception");
                }
    
                this.transactionManager.commit(status);
                return result;
            }
        }
    
        private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
            this.logger.debug("Initiating transaction rollback on application exception", ex);
    
            try {
                this.transactionManager.rollback(status);
            } catch (TransactionSystemException var4) {
                this.logger.error("Application exception overridden by rollback exception", ex);
                var4.initApplicationException(ex);
                throw var4;
            } catch (RuntimeException var5) {
                this.logger.error("Application exception overridden by rollback exception", ex);
                throw var5;
            } catch (Error var6) {
                this.logger.error("Application exception overridden by rollback error", ex);
                throw var6;
            }
        }
    }
    复制代码

    基于上面的模板类,我们可以这样来实现数据库的事务,把每个逻辑都写在TransactionCallback.doInTransaction()方法里面,他会自动帮我们提交事务

    复制代码
    TransactionTemplate transactionTemplate=new TransactionTemplate();
    transactionTemplate.setTransactionManager(platformTransactionManager);
            
            transactionTemplate.execute(new TransactionCallback<String>() {
    
                @Override
                public String doInTransaction(TransactionStatus status) {
                    //数据库操作
                    return "success";
                }
            });
    复制代码

    但是这样会使每个数据库方法都要要写到TransactionCallback.doInTransaction(),其实耦合度还是很高。Spring于是推出了他的AOP管理事务

    这个我会在下一篇详细介绍spring-aop与事务

    转载:http://www.cnblogs.com/zwt1990/p/7096492.html

  • 相关阅读:
    onInterceptTouchEvent 与 onTouchEvent 分析与MotionEvent在ViewGroup与View中的分发
    不用windows不会死
    iframe动态改变内嵌页面高度
    算法5-8:矩形相交
    浅析数据库连接池(二)
    Ubuntu下(Linux+Apache+MYSQL+PHP, LAMP)环境搭建
    unix环境高级编程----进程控制wait()
    centos7 通过kvm+vnc 实现远程桌面虚拟化和创建windows、Linux虚拟机
    Android native层动态库注射
    Windows10 下 JAVA JDK版本设置修改操作
  • 原文地址:https://www.cnblogs.com/cainiao-Shun666/p/9177044.html
Copyright © 2011-2022 走看看