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与事务

  • 相关阅读:
    Knockout应用开发指南 第八章:简单应用举例(2)
    微软ASP.NET站点部署指南(7):生产环境部署
    Knockout应用开发指南 第七章:Mapping插件
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(6)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(5)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(3)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(8)
    Microsoft Visual Studio .NET 2003 引导程序插件下载地址(非官方)
    Vs2010在没有安装SQL Server 2005/2008 Express时如何连接MDF数据文件?
  • 原文地址:https://www.cnblogs.com/zwt1990/p/7096492.html
Copyright © 2011-2022 走看看