Spring源代码分析(14)---Spring事务(兵来将挡,水来土淹)

81 篇文章 0 订阅
36 篇文章 0 订阅
Spring的事务及其的灵活,他构建在AOP的基础上,采用事务声明的方式,使得我们很容易在hibernate jdbc,jta等事务方式中切换;
在前几节,我们重新复习了数据源,连接池,以及分布式事务的知识,在这一节中,我们详细的来分析一下Spring的事务的实现;
Spring事务的实现是建立在Aop的基础上,在Aop的基础上,Spring避免了硬编码的事务声明方式,改在配置文件中声明,从而增强了灵活性,并且了紧耦合;
首先,我们来看一下Spring的配置文件的生成;

<bean id="coreyDao" name="coreyDao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        abstract="false" lazy-init="default" autowire="default"
        dependency-check="default">
        <property name="target">
            <ref bean="coreyRealDao"></ref>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager"></ref>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>


我们通过获取了coreyDao能够得到一个具有事务的coreyRealDao的代理对象,他的代理规则被详细的描述在transactionAttributes的properties中;
那么,现在,我们就开始分析一个个具体的类;




从上面的类图我们可以看见,首先由一个代理类代理了普通的数据库事务类,这个ProxyFactoryBean含有一个拦截器,并且对拦截器进行初始化;


下面是该ProxyFacrotyBean的属性;
       
        //拦截器;
    private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();  
        
        //代理的目标类。同proxyFactoryBean
    private Object target;
       
        //代理接口
    private Class[] proxyInterfaces;
       
        //切面;
    private Pointcut pointcut;
       
        //前拦截器
    private Object[] preInterceptors;
       
        //后拦截器
    private Object[] postInterceptors;
       
        //最后生成的代理类,利用FactoryBean的getObject()返回;
    private Object proxy;



在这个类中,我们可以设置transactionAttributes,PlatformTransactionManager等等,目的是初始化transactionInterceptor;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionInterceptor.setTransactionManager(transactionManager);
    }


        public void setTransactionAttributes(Properties transactionAttributes) {
        this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
    }


    public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
        this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
    }
在下面这段中,实现了一个非常有趣的功能;
    public void setBeanFactory(BeanFactory beanFactory) {
        if (this.transactionInterceptor.getTransactionManager() == null &&
                beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory lbf = (ListableBeanFactory) beanFactory;
            PlatformTransactionManager ptm = (PlatformTransactionManager)
                    BeanFactoryUtils.beanOfTypeIncludingAncestors(lbf, PlatformTransactionManager.class);
            this.transactionInterceptor.setTransactionManager(ptm);
        }
    }
如果我们没有显示的为该ProxyFactoryBean制定TM,那么就会默认把ioc容器里面的唯一的一个PlatformTransactionManager类型的bean设置给他(但是如果超过一个,就会抛出异常);

其下,我们来好好琢磨琢磨这个具有事务功能的代理类是如何生成的;

    public void afterPropertiesSet() {

                //这个类判断你是否设置了TM和transactionAttributes
        this.transactionInterceptor.afterPropertiesSet();

                //检查是否设置类代理的目标类
        if (this.target == null) {
            throw new IllegalArgumentException("'target' is required");
        }
                //代理类不能为String类型;
        if (this.target instanceof String) {
            throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
        }
                
                //实例化代理工厂,为生成代理类做准备,我们在AOP一节已经分析过了;
        ProxyFactory proxyFactory = new ProxyFactory();
               
                //结合我们所提供的装备和接口以及切面,生成了一个代理类;
        if (this.preInterceptors != null) {
            for (int i = 0; i < this.preInterceptors.length; i++) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));
            }
        }

        if (this.pointcut != null) {
            Advisor advice = new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
            proxyFactory.addAdvisor(advice);
        }
        else {
            // Rely on default pointcut.
            proxyFactory.addAdvisor(new TransactionAttributeSourceAdvisor(this.transactionInterceptor));
            // Could just do the following, but it's usually less efficient because of AOP advice chain caching.
            // proxyFactory.addAdvice(transactionInterceptor);
        }

        if (this.postInterceptors != null) {
            for (int i = 0; i < this.postInterceptors.length; i++) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));
            }
        }

        proxyFactory.copyFrom(this);

        TargetSource targetSource = createTargetSource(this.target);
        proxyFactory.setTargetSource(targetSource);

        if (this.proxyInterfaces != null) {
            proxyFactory.setInterfaces(this.proxyInterfaces);
        }
        else if (!isProxyTargetClass()) {
            // Rely on AOP infrastructure to tell us what interfaces to proxy.
            proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
        }
       
                //代理类生成了;
        this.proxy = getProxy(proxyFactory);
    }


经过上面的步骤,我们已经知道了代理类的生成过程,那么这个代理类是如何具有事务功能的呢,我们只知道他被transactionInterceptor进行了拦截,那么在这个拦截器中具体做了什么样的操作,我们再来具体的分析一下transactionInterceptor;




上图我们可看见了transactionInterceptor的基本的类图,他包含一组TransactionInfo,TransactionInfo是线程变量,这说明,一个线程只可能拥有一个TransactionInfo,线程和线程之间的事务是互不关联,互不影响,线程安全的;
ThreadLocal我们在前几节已经介绍了:

    private static final ThreadLocal currentTransactionInfo = new ThreadLocal();


    public static TransactionStatus currentTransactionStatus() throws NoTransactionException {
        return currentTransactionInfo().transactionStatus;
    }
       
           protected static TransactionInfo currentTransactionInfo() throws NoTransactionException {
        TransactionInfo info = (TransactionInfo) currentTransactionInfo.get();
        if (info == null) {
            throw new NoTransactionException("No transaction aspect-managed TransactionStatus in scope");
        }
        return info;
    }


事务管理器对系统的事务进行同意管理,在这里PlatformTransactionManager 屏蔽了事务管理器之间的不同,比如jdbc事务管理,hibernate事务管理,jms事务管理等等,在这里,使得事务的实现和事务管理器之间解耦开来,跟我们前几节中大对象的生成了数据库之间的耦合有异曲同工之妙,到时候,我们只要改变配置就可以更换事务的实现;

protected PlatformTransactionManager transactionManager;



现在,有人不仅仅要问,代理类是怎么知道在目标代理类中,什么方法(现在事务声明的细粒度是方法)需要进行事务管理,什么方法不要,下面我们就会说到这个功能的实现;

protected TransactionAttributeSource transactionAttributeSource;



public interface TransactionAttributeSource {

   
    TransactionAttribute getTransactionAttribute(Method method, Class targetClass);

}


TransactionAttributeSource 是一个TransactionAttribute的管理类,他有许多具体的实现,其中最为常用的是也是默认的是:

在transactionInterceptor初始化的时候:
        public void setTransactionAttributes(Properties transactionAttributes) {
        NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
        tas.setProperties(transactionAttributes);
        this.transactionAttributeSource = tas;
    }

NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();被作为了默认的实现,我们现在来看看看这个
NameMatchTransactionAttributeSource类的实现细节;他含有一个hashMap来存储transactionAttribute,其中transactionAttribute为值,需要拦截的方法为key;
  
                     private Map nameMap = new HashMap();


            public void setProperties(Properties transactionAttributes) {
        TransactionAttributeEditor tae = new TransactionAttributeEditor();
        for (Iterator it = transactionAttributes.keySet().iterator(); it.hasNext(); ) {
            String methodName = (String) it.next();
            String value = transactionAttributes.getProperty(methodName);
            tae.setAsText(value);
            TransactionAttribute attr = (TransactionAttribute) tae.getValue();

                        //形成方法名和事务属性对象的映射;
            addTransactionalMethod(methodName, attr);
        }
    }

我们可以从上看见properties的entry到transactionAttribute的转换,这个是从value到Object的转换,这让我们想起了什么,对就是textEditor,我们来看看TransactionAttributeEditor是怎么进行这次移花接木的:


  public void setAsText(String text) throws IllegalArgumentException {
        if (StringUtils.hasLength(text)) {


                //把<prop key="*">PROPAGATION_REQUIRED,timeout_21,ISOLATIONXX</prop>中的PROPAGATION_REQUIRED拿出来用                        //逗号隔开,分成数组;

            String[] tokens = StringUtils.commaDelimitedListToStringArray(text);
                       
                        //生成RuleBasedTransactionAttribute();
            RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute();
            for (int i = 0; i < tokens.length; i++) {
                               
                                //除去前后空白字符串
                String token = StringUtils.trimWhitespace(tokens[i].trim());
       
                                如果中间含有空白字符,抛出异常;
                if (StringUtils.containsWhitespace(token)) {
                    throw new IllegalArgumentException(
                            "Transaction attribute token contains illegal whitespace: [" + token + "]");
                }
               
                                //辨别属性,并且设置到RuleBasedTransactionAttribute相应的属性字段里面;
                if (token.startsWith(TransactionDefinition.PROPAGATION_CONSTANT_PREFIX)) {
                    attr.setPropagationBehaviorName(token);
                }
                else if (token.startsWith(TransactionDefinition.ISOLATION_CONSTANT_PREFIX)) {
                    attr.setIsolationLevelName(token);
                }
                else if (token.startsWith(DefaultTransactionAttribute.TIMEOUT_PREFIX)) {
                    String value = token.substring(DefaultTransactionAttribute.TIMEOUT_PREFIX.length());
                    attr.setTimeout(Integer.parseInt(value));
                }
                else if (token.equals(DefaultTransactionAttribute.READ_ONLY_MARKER)) {
                    attr.setReadOnly(true);
                }
                else if (token.startsWith(DefaultTransactionAttribute.COMMIT_RULE_PREFIX)) {
                    attr.getRollbackRules().add(new NoRollbackRuleAttribute(token.substring(1)));
                }
                else if (token.startsWith(DefaultTransactionAttribute.ROLLBACK_RULE_PREFIX)) {
                    attr.getRollbackRules().add(new RollbackRuleAttribute(token.substring(1)));
                }
                else {
                    throw new IllegalArgumentException("Invalid transaction attribute token: [" + token + "]");
                }
            }
            setValue(attr);
        }
        else {
            setValue(null);
        }
    }



到时候如何取出这个事务属性对象呢,我们看见在配置文件中有配置*,这好像是正则表达式的应用,但是很遗憾的是,这里并不支持完整的正则表达式匹配,只是支持简单的行首和行尾的*代表任意多的任意字符而已,不过,这是一个很好的扩展点,我们自己可以试着实现;

public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
        //首先,得到方法元对象的方法名字;
        String methodName = method.getName();
                //从hashMap中取出;
        TransactionAttribute attr = (TransactionAttribute) this.nameMap.get(methodName);

        if (attr == null) {
            //如果为空;进行*的匹配
            String bestNameMatch = null;
            for (Iterator it = this.nameMap.keySet().iterator(); it.hasNext();) {
                String mappedName = (String) it.next();

                                //*号开头的只要能匹配后面的字符即可,*结尾的只要能匹配前面的字符串即可;
                if (isMatch(methodName, mappedName) &&
                        (bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
                    attr = (TransactionAttribute) this.nameMap.get(mappedName);
                    bestNameMatch = mappedName;
                }
            }
        }

        return attr;
    }


//*号开头的只要能匹配后面的字符即可,*结尾的只要能匹配前面的字符串即可;
protected boolean isMatch(String methodName, String mappedName) {
        return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) ||
                (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length())));
    }



接下来,我们可以先来看下,到底这个transactionAttribute这个对象;


public interface TransactionDefinition {

    String PROPAGATION_CONSTANT_PREFIX = "PROPAGATION";

    String ISOLATION_CONSTANT_PREFIX = "ISOLATION";

        //传播途径
    int getPropagationBehavior();

    //隔离级别
    int getIsolationLevel();

    //有效时间
    int getTimeout();

    //是否只读
    boolean isReadOnly();

    //对象名字
    String getName();

}




public interface TransactionAttribute extends TransactionDefinition {
   
    //在此基础上增加了回滚判断机制,以便事务在遇到制定异常的时候进行回滚;
    boolean rollbackOn(Throwable ex);
   
}

在下面,我们来介绍一下TransactionInfo;TransactionInfo其实就犹如TransactionAttributeSource hashMap中的一项;
TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性

    protected class TransactionInfo {

        private final TransactionAttribute transactionAttribute;

        private final Method method;

        private TransactionStatus transactionStatus;

        private TransactionInfo oldTransactionInfo;

        public TransactionInfo(TransactionAttribute transactionAttribute, Method method) {
            this.transactionAttribute = transactionAttribute;
            this.method = method;
        }

下面我们来看一下,这个拦截器的具体的拦截方式把;
public Object invoke(MethodInvocation invocation) throws Throwable {
        //获取代理目标类的类型;
        Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);

        //根据当前拦截的方法,取得一个相对应的transactionInfo,不过当然不一定就有,所以名字都叫necessary;
        TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);

        Object retVal = null;
        try {
            //执行该方法;
            retVal = invocation.proceed();
        }
        catch (Throwable ex) {
            //如果方法抛出异常,那么采用异常处理机制;
            doCloseTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
                        //采用finally处理;
            doFinally(txInfo);
        }
                //正常结束的处理;
        doCommitTransactionAfterReturning(txInfo);
        return retVal;
    }

在开始的时候,我们的TransactionAttributeSource只是存储了代表方法的字符串和TransactionAttribute的对应哈西表,但没有建立方法对象Method实例与TransactionAttribute之间的对应,那么createTransactionIfNecessary就是为了实现这个功能;


protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {

        // 根据方法找到对应的TransactionAttribute对象,如果没有找到的话,那么该方法就不会被拦截;

        final TransactionAttribute sourceAttr =
                this.transactionAttributeSource.getTransactionAttribute(method, targetClass);
        TransactionAttribute txAttr = sourceAttr;

        // 如果该TransacrionAttribute没有设置名字,那么会根据将className.methodName作为该TransactionAttribute的名字,
                //这里是典型的代理模式的应用;
        if (txAttr != null && txAttr.getName() == null) {
            final String name = methodIdentification(method);
            txAttr = new DelegatingTransactionAttribute(sourceAttr) {
                public String getName() {
                    return name;
                }
            };
        }
               
                //生成了method和transactionAttribute相对应的transactionInfo实例;

        TransactionInfo txInfo = new TransactionInfo(txAttr, method);
        if (txAttr != null) {
            // We need a transaction for this method
            if (logger.isDebugEnabled()) {
                logger.debug("Getting transaction for " + txInfo.joinpointIdentification());
            }

            // The transaction manager will flag an error if an incompatible tx already exists
            txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));
        }
        else {
            // The TransactionInfo.hasTransaction() method will return
            // false. We created it only to preserve the integrity of
            // the ThreadLocal stack maintained in this class.
            if (logger.isDebugEnabled())
                logger.debug("Don't need to create transaction for [" + methodIdentification(method) +
                        "]: this method isn't transactional");
        }

            //在这里,我们可以看见这个transactionInfo绑定到该线程上去;
                //如果当前线程存在未结束的事务,那么我们会把旧transactionInfo设置为新的transactionInfo的oldTransactionInfo
        txInfo.bindToThread();
        return txInfo;
    }
                
                //保存旧的transactionInfo是因为考虑到事务传播途径的判断;
                private void bindToThread() {
            // Expose current TransactionStatus, preserving any existing transactionStatus for
            // restoration after this transaction is complete.
            oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get();
            currentTransactionInfo.set(this);
        }

事务的新状态;


    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
                //留给子类实现,比如jdbc会获取DatabaseTransaction,而jta会从jndi获取UserTrasction获取transaction
        Object transaction = doGetTransaction();

        // Cache debug flag to avoid repeated checks.
        boolean debugEnabled = logger.isDebugEnabled();
        if (debugEnabled) {
            logger.debug("Using transaction object [" + transaction + "]");
        }

        if (definition == null) {
            //如果为空,就会创建一个默认的trasnactionDefinition;
            definition = new DefaultTransactionDefinition();
        }

        if (isExistingTransaction(transaction)) {
            //处理已经存在的transaction,返回其状态;
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

        // Check definition settings for new transaction.
        if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
            throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
        }

        // No existing transaction found -> check propagation behavior to find out how to proceed.
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }
        else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            Object suspendedResources = suspend(null);
            if (debugEnabled) {
                logger.debug("Creating new transaction with name [" + definition.getName() + "]: " +

definition);
            }
            doBegin(transaction, definition);
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            return newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        }
        else {
            // Create "empty" transaction: no actual transaction, but potentially synchronization.
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
        }
    }
   
         //会根据传播途径来返回相应的事务状态类;
         private TransactionStatus handleExistingTransaction(
            TransactionDefinition definition, Object transaction, boolean debugEnabled)
            throws TransactionException {

                //never不能处在事务中,否则抛出异常;
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
            throw new IllegalTransactionStateException(
                    "Existing transaction found for transaction marked with propagation 'never'");
        }
               
                //NOT_SUPPORTED不能处在事务中,否则将当前事务挂起;
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction");
            }
                        //挂起当前事务;
            Object suspendedResources = suspend(transaction);
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
                        //不是新的事务;
            return newTransactionStatus(
                    definition, null, false, newSynchronization, debugEnabled, suspendedResources);
        }
                //REQUIRES_NEW要求挂起当前事务并且要求一个新的事务;
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction, creating new transaction with name [" +
                        definition.getName() + "]");
            }
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
            try {   
                doBegin(transaction, definition);
            }
            catch (TransactionException beginEx) {
                try {
                    resume(transaction, suspendedResources);
                }
                catch (TransactionException resumeEx) {
                    logger.error(
                            "Inner transaction begin exception overridden by outer transaction

resume exception", beginEx);
                    throw resumeEx;
                }
                throw beginEx;
            }
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                        //新的事务;
            return newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        }
                //PROPAGATION_NESTED代表嵌入式事务;
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            if (!isNestedTransactionAllowed()) {
                throw new NestedTransactionNotSupportedException(
                        "Transaction manager does not allow nested transactions by default - " +
                        "specify 'nestedTransactionAllowed' property with value 'true'");
            }
            if (debugEnabled) {
                logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
            }
            if (useSavepointForNestedTransaction()) {
                //生成新的储存点
                DefaultTransactionStatus status =
                        newTransactionStatus(definition, transaction, false, false, debugEnabled,

null);
                status.createAndHoldSavepoint();
                return status;
            }
            else {
                               
                                //在这里会开始新的事务,至于这个新的事务如何开始,与具体的实现有关系,所以会利通模板模式
                                //推迟到子类中实现,比如下面的两种实现方式;
                doBegin(transaction, definition);
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled,

null);
            }
        }

        // Assumably PROPAGATION_SUPPORTS.
        if (debugEnabled) {
            logger.debug("Participating in existing transaction");
        }
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        return newTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
    }
JDBC的doBegin:
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            if (txObject.getConnectionHolder() == null ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.getConnection();
                if (logger.isDebugEnabled()) {
                    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);

            // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
            // so we don't want to do it unnecessarily (for example if we've explicitly
            // configured the connection pool to set it already).
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);

            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            // Bind the session holder to the thread.
            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(getDataSource(),

txObject.getConnectionHolder());
            }
        }

        catch (SQLException ex) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }
利用了JDBC的setAutoCommit()来实现事务的开始;

JTA事务的doBegin:
    protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
            throws NotSupportedException, SystemException {

        applyIsolationLevel(txObject, definition.getIsolationLevel());
        applyTimeout(txObject, definition.getTimeout());
        txObject.getUserTransaction().begin();
    }
利用了Usertransaction.begin来实现事务的开始;




事务状态的5个基本属性;

    public DefaultTransactionStatus(
        Object transaction, boolean newTransaction, boolean newSynchronization,
            boolean readOnly, boolean debug, Object suspendedResources) {
               
                //当前事务属性的事务
        this.transaction = transaction;

                //是否是一个新的事务;
        this.newTransaction = newTransaction;

                //事务同步
        this.newSynchronization = newSynchronization;

                //这个事务是只读事务;
        this.readOnly = readOnly;
       
                //是否显示调试信息;
                this.debug = debug;

                //当前事务的被挂载起来的资源装载对象;
        this.suspendedResources = suspendedResources;
    }
       
        //在方法拦截中,会根据不同的传播途径生成的事务状态来执行不同的操作;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be <code>null</code>.
        // The TransactionAttributeSource should be passed the target class
        // as well as the method, which may be from an interface
        Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);

        // Create transaction if necessary.
        TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);

        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.proceed();
        }
        catch (Throwable ex) {
            // target invocation exception
            doCloseTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            doFinally(txInfo);
        }
        doCommitTransactionAfterReturning(txInfo);
        return retVal;
    }

}

doFinally操作是无论那个方法不管什么事务属性都会要做的:
    protected void doFinally(TransactionInfo txInfo) {
        if (txInfo != null) {
            txInfo.restoreThreadLocalStatus();
        }
    }

他把上一个事务信息传入了线程中间,回复了当前线程的事务信息;
在这里,jiwenke发表在javaeye中的解释,已经很详细了:

其中的doFinally(txInfo)那一行很重要,也就是说不管如何,这个doFinally方法都是要被调用的,为什么它这么重要呢,举个例子:
我们还是以propregation_required来举例子吧,假设情况是这样的,AService中有一个方法调用了BService中的,这两个方法都处在事务体之

中,他们的传播途径都是required。那么调用开始了,AService的方法首先入方法栈,并创建了 TransactionInfo的实例,接着BService的方

法入栈,又创建了一个TransactionInfo的实例,而重点要说明的是 TransactionInfo是一个自身关联的内部类,第二个方法入栈时,会给新创

建的TransactionInfo的实例设置一个属性,就是 TransactionInfo对象中的private TransactionInfo oldTransactionInfo;属性,这个属性

表明BService方法的创建的TransactionInfo对象是有一个old的 transactionInfo对象的,这个oldTransactionInfo对象就是AService方法入

栈时创建的 TransactionInfo对象,我们还记得在createTransactionIfNecessary方法里有这样一个方法吧:

protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
                // We always bind the TransactionInfo to the thread, even if we didn't create
        // a new transaction here. This guarantees that the TransactionInfo stack
        // will be managed correctly even if no transaction was created by this aspect.
        txInfo.bindToThread();
        return txInfo;
    }

就是这个bindToThread()方法在作怪:
private void bindToThread() {
            // Expose current TransactionStatus, preserving any existing transactionStatus for
            // restoration after this transaction is complete.
            oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get();
            currentTransactionInfo.set(this);
        }


如果当前线程中已经有了一个TransactionInfo,则拿出来放到新建的transactionInfo对象的oldTransactionInfo属性中,然后再把新建的Tra

nsactionInfo设置到当前线程中。

这里有一个概念要搞清楚,就是TransactionInfo对象并不是表明事务状态的对象,表明事务状态的对象是TransactionStatus对象,这个对象

同样是TransactionInfo的一个属性(这一点,我在前面一篇文章中并没有讲清楚)。

接下来BService中的那个方法返回,那么该它退栈了,它退栈后要做的就是doFinally方法,即把它的 oldTransactionInfo设置到当前线程中

(这个TransactionInfo对象显然就是AService方法入栈时创建的,怎么现在又要设置到线程中去呢,原因就是BService的方法出栈时并不提交

事务,因为BService的传播途径是required,所以要把栈顶的方法所创建 transactioninfo给设置到当前线程中),即调用AService的方法时

所创建的TransactionInfo对象。那么在 AServie的方法出栈时同样会设置TransactionInfo对象的oldTransactionInfo到当前线程,这时候显

然 oldTransactionInfo是空的,但AService中的方法会提交事务,所以它的oldTransactionInfo也应该是空了。

在这个小插曲之后,么接下来就应该是到提交事务了,之前在AService的方法出栈时,我们拿到了它入栈时创建的 TransactionInfo对象,这

个对象中包含了AService的方法事务状态。即TransactionStatus对象,很显然,太显然了,事务提交中的任何属性都和事务开始时的创建的对

象息息相关,这个TransactionStatus对象哪里来的,我们再回头看看 createTransactionIfNessary方法吧:

如果事务是一个独立的新事务的话,那么就会提交,不然不会做出动作,而把提交的动作给了doFinally中恢复的oldTrasactionInfo了;

    protected void doCommitTransactionAfterReturning(TransactionInfo txInfo) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking commit for transaction on " + txInfo.joinpointIdentification());
            }
            this.transactionManager.commit(txInfo.getTransactionStatus());
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值