`

spring 事务

阅读更多
spring的事务是从TransactionProxyFactoryBean开始的TransactionProxyFactoryBean也是一个FactoryBean

源码如下:
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
    implements BeanFactoryAware
{

    public TransactionProxyFactoryBean()
    {
    }

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

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

    public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource)
    {
        transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
    }

    public void setPointcut(Pointcut pointcut)
    {
        this.pointcut = pointcut;
    }

    public void setBeanFactory(BeanFactory beanFactory)
    {
        transactionInterceptor.setBeanFactory(beanFactory);
    }

    protected Object createMainInterceptor()
    {
        transactionInterceptor.afterPropertiesSet();
        if(pointcut != null)
            //设置默认的通知器
            return new DefaultPointcutAdvisor(pointcut, transactionInterceptor);
        else
            //使用事务属性通知器
            return new TransactionAttributeSourceAdvisor(transactionInterceptor);
    }

    private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
    private Pointcut pointcut;
}

那么transactionInterceptor这个拦截器是在什么时候启动的。
我们在AbstractSingletonProxyFactoryBean中可以看到产生事务代理对象是在该类中的afterPropertiesSet方法中,其源码如下:
public void afterPropertiesSet()
    {
        if(target == null)
            throw new IllegalArgumentException("Property 'target' is required");
        if(target instanceof String)
            throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
        if(proxyClassLoader == null)
            proxyClassLoader = ClassUtils.getDefaultClassLoader();
        ProxyFactory proxyFactory = new ProxyFactory();
        if(preInterceptors != null)
        {
            Object aobj[];
            int k = (aobj = preInterceptors).length;
            for(int i = 0; i < k; i++)
            {
                Object interceptor = aobj[i];
                proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(interceptor));
            }

        }
        //配置通知器
        proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(createMainInterceptor()));
        if(postInterceptors != null)
        {
            Object aobj1[];
            int l = (aobj1 = postInterceptors).length;
            for(int j = 0; j < l; j++)
            {
                Object interceptor = aobj1[j];
                proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(interceptor));
            }

        }
        proxyFactory.copyFrom(this);
       
        if(proxyInterfaces != nullTargetSource targetSource = createTargetSource(target);
        //设置目标接口
        proxyFactory.setTargetSource(targetSource);)
            //设置代理接口
            proxyFactory.setInterfaces(proxyInterfaces);
        else
        if(!isProxyTargetClass())
            proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), proxyClassLoader));
        proxy = proxyFactory.getProxy(proxyClassLoader);
    }

Spring事务处理完成AOP配置的地方,这个afterPropertiesSet方法功能实现如下代码


下面我们分析下事务属性的读入
从TransactionProxyFactoryBean中我们可以看到TransactionAttributeSourceAdvisor,我们以这个类为入口从而了解事务属性是如何注入的
TransactionAttributeSourceAdvisor 是一个通知器包含了切面和通知

public TransactionAttributeSourceAdvisor()
    {
        pointcut = new TransactionAttributeSourcePointcut() {

            protected TransactionAttributeSource getTransactionAttributeSource()
            {
                return transactionInterceptor == null ? null : transactionInterceptor.getTransactionAttributeSource();
            }

            final TransactionAttributeSourceAdvisor this$0;

           
            {
                this$0 = TransactionAttributeSourceAdvisor.this;
                super();
            }
        }
;
    }

在声明式事务处理中,是通过对目标对象的方法调用拦截实现,这个拦截通过AOP发挥过作用。对于拦截器启动,首先需要对方法调用是否需要拦截器进行判断,而判断的依据是那些在TrasactionProxyFactoryBean中为目标对象设置的事务属性。也就是说需要判断当前的目标方法调用是不是一个配置好的,需要进行事务处理方法调用。具体说,这个匹配判断在TransactionAtrributeSourcePoincut中完成,它的实现如代码如下:
    public boolean matches(Method method, Class targetClass)
    {
        TransactionAttributeSource tas = getTransactionAttributeSource();
        return tas == null || tas.getTransactionAttribute(method, targetClass) != null;
    }

在pointcut的matches判断过程中,会用到transactionAttributeSource对象,这个对象是在对TranasactionInterceptor进行依赖注入时就配置好了的。它的设置是在基类TransactionAspectSupport完成的,配置了一个NameMatchTransactionAttributeSource代码如下:

public void setTransactionAttributes(Properties transactionAttributes)
    {
        NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
        tas.setProperties(transactionAttributes);
        transactionAttributeSource = tas;
    }


在应用调用目标方法的时候,因为这个目标方法已经被TrasactionProxyFactoryBean代理,所以TrasactionProxyFactoryBean需要判断这个方法是否是事务方法。这个判断的实现,是通过NameMatchTransactionAttributeSource中,能否为这个调用方法事务属性来完成的.具体的实现过程是这样的: 首先,使用调用方法作为索引的namemap中去查找相应的事务处理性值,如果能够找到,那么就说明调用方法和事务方法直接对应,如果找不到,那么就会遍历整个nameMap,对保存在其中的每一个方法名,使用PatternMatchUtils进行命名模式上的匹配。这里使用PatternMatchUtils进行匹配,是因为在设置事务方法的时候,就像我们常见的那样,可以不需要为事务设置一个完整的方法名,而是可以通过设置方法名的命名模式来完成,比如可以通过像对通配符*的使用。

我们看下NameMatchTransactionAttributeSource中的setProperties方法
public void setProperties(Properties transactionAttributes)
    {
        TransactionAttributeEditor tae = new TransactionAttributeEditor();
        String methodName;
        TransactionAttribute attr;
        for(Enumeration propNames = transactionAttributes.propertyNames(); propNames.hasMoreElements(); addTransactionalMethod(methodName, attr))
        {
            methodName = (String)propNames.nextElement();
            String value = transactionAttributes.getProperty(methodName);
            tae.setAsText(value);
            attr = (TransactionAttribute)tae.getValue();
        }

    }
  public TransactionAttribute getTransactionAttribute(Method method, Class targetClass)
    {
         //判断当前目标调用的方法与配置事务方法,是否匹配
        String methodName = method.getName();
        TransactionAttribute attr = (TransactionAttribute)nameMap.get(methodName);
        if(attr == null)
        {
            String bestNameMatch = null;
            for(Iterator iterator = nameMap.keySet().iterator(); iterator.hasNext();)
            {
                String mappedName = (String)iterator.next();
                if(isMatch(methodName, mappedName) && (bestNameMatch == null || bestNameMatch.length() <= mappedName.length()))
                {
                    attr = (TransactionAttribute)nameMap.get(mappedName);
                    bestNameMatch = mappedName;
                }
            }

        }
        return attr;
    }


通过以上过程,可以得到与目标对象调用方法相关TransactionAttribute对象,在这个对象中,封装了事务处理的配置。


事务处理拦截器的实现

在完成以上准备工作后,经过TransactionProxyFactoryBean的AOP包装,此时如果对目标对象进行方法调用,其调用起作用对象实际是一个proxy代理对象,对目标对象方法的调用,不会直接作用在TransactionProxyFactoryBean设置的目标对象上,而会被设置的事务处理拦截器,而对于TransactionProxyFactoryBean的AOP实现中,获取Proxy对象的过程,这个过程并不复杂,TransactionProxyFactoryBean作为一个Factorybean,对这个bean对象的引用,是通过调用TransactionProxyFactoryBean的getObject方法来得到的,我们对这个方法已经很熟悉了

public Object getObject()
    {
        if(proxy == null)
            throw new FactoryBeanNotInitializedException();
        else
            return proxy;
    }

关于如何对AOP代理作用可以看下spring中AOP源码的分析,我们可以注意下TransactionInteceptor中的invoke方法其源码如下:

public Object invoke(final MethodInvocation invocation) throws Throwable {  
    //这里得到目标对象  
    Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);  
 
    //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,  
    //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource  
    final TransactionAttribute txAttr =  
            getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);  
    final String joinpointIdentification = methodIdentification(invocation.getMethod());  
 
    //这里判断我们使用了什么TransactionManager  
    if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {  
        // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去  
        TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);  
        Object retVal = null;  
        try {  
              retVal = invocation.proceed();  
        }  
        catch (Throwable ex) {  
            // target invocation exception  
            completeTransactionAfterThrowing(txInfo, ex);  
            throw ex;  
        }  
        finally {  
            cleanupTransactionInfo(txInfo);  
        }  
        commitTransactionAfterReturning(txInfo);  
        return retVal;  
    }  
 
    else {  
        // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。  
        try {  
            Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,  
                    new TransactionCallback() {  
                        public Object doInTransaction(TransactionStatus status) {  
                            //同样的需要一个TransactonInfo  
                            TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);  
                            try {  
                                return invocation.proceed();  
                            }    
                    });  
    }  



在invoke方法中我们可以看到,首先先获得调用方法的事务处理配置,在得到事务处理配置以后,会取得PlatformTranasctionManager由这个事务处理器来实现事务的创建、提交、回滚操作。PlatformTranasctionManager是在IOC容器中配置的。我们比较熟悉有DataSourceTransactionManager和HiberanteTransactionManager等。
分享到:
评论

相关推荐

    Spring事务流程图

    Spring事务管理是Spring框架的核心特性之一,主要用于处理应用程序中的数据一致性问题。在Spring中,事务管理分为编程式和声明式两种方式。本篇文章将详细解释Spring事务管理的流程,以及如何通过时序图来理解这一...

    Spring事务管理Demo

    Spring事务管理的目的是确保数据的一致性和完整性,尤其是在多操作、多资源的环境中。本Demo将深入探讨Spring如何实现事务的管理。 首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 ...

    spring事务与数据库操作

    ### Spring事务与数据库操作 #### 一、Spring的声明式事务管理 在现代软件开发中,事务处理是非常关键的一部分,特别是在涉及多个数据操作时。Spring框架提供了强大的事务管理能力,可以方便地集成到应用程序中。...

    Spring事务管理开发必备jar包

    本资源包提供了进行Spring事务管理开发所需的所有关键库,包括框架基础、核心组件、AOP(面向切面编程)支持、日志处理、编译工具以及与数据库交互的相关jar包。下面将对这些知识点进行详细解释: 1. **Spring框架*...

    Spring事务原理、Spring事务配置的五种方式

    Spring事务原理和配置 Spring事务原理是指Spring框架中的一种机制,用于管理事务,并提供了多种配置方式。事务是指一系列的操作,作为一个整体执行,如果其中某个操作失败,整个事务将回滚。Spring事务原理围绕着两...

    spring事务案例分析.zip

    本主题将深入探讨“Spring事务案例分析.zip”中的关键知识点,包括Spring事务管理及其在实际项目中的应用。 首先,我们来了解什么是Spring事务管理。在分布式系统或数据库操作中,事务管理是确保数据一致性和完整性...

    Spring事务管理失效原因汇总

    标题“Spring事务管理失效原因汇总”指出了本文的核心内容是分析在使用Spring框架进行事务管理时可能遇到的问题及其原因。描述部分进一步说明了事务失效的后果往往不明显,容易在测试环节被忽略,但在生产环境中出现...

    spring 事务传播 demo

    在Spring框架中,事务管理是核心特性之一,它允许开发者以声明式或编程式的方式处理事务。本示例“spring 事务传播 demo”将聚焦于Spring的事务传播行为,这是在多个方法调用中控制事务边界的关键概念。下面我们将...

    Spring事务管理的jar包

    本篇将深入探讨Spring事务管理的核心概念、工作原理以及如何使用`spring-tx-3.2.0.RELEASE.jar`这个jar包。 首先,我们需要理解什么是事务。在数据库系统中,事务是一组操作,这些操作被视为一个整体,要么全部完成...

    Spring事务小demo

    这个名为"Spring事务小demo"的项目提供了一个实践示例,帮助开发者了解Spring事务处理的基本概念和用法。 首先,Spring事务管理是Spring框架的核心特性之一,它允许我们以声明式或编程式的方式管理事务。声明式事务...

    Spring 事务简单完整例子

    本文将深入探讨在Spring框架中如何管理事务,以“Spring 事务简单完整例子”为出发点,结合标签“spring,事务,jdbc事务”,我们将详细解释Spring事务管理的原理和实践。 首先,Spring提供了两种事务管理方式:编程...

    Spring事务详细讲解

    Spring事务详细讲解 在 Spring 框架中,事务管理扮演着非常重要的角色。Spring 声明式事务让我们从复杂的事务处理中得到解脱,使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要...

    SPRING事务机制DEMO

    Spring事务机制是Java开发中非常重要的一个概念,它在企业级应用中扮演着核心角色,确保数据的一致性和完整性。Spring提供了多种事务管理方式,包括编程式事务管理和声明式事务管理。在这篇DEMO中,我们将重点探讨...

    spring 事务传播与隔离级别DEMO

    本DEMO主要探讨的是Spring事务的传播行为和隔离级别,这些概念对于理解和优化数据库操作至关重要。让我们深入理解这些概念及其实际应用。 首先,我们来谈谈事务的传播行为。在Spring中,当一个方法被另一个具有事务...

    Spring事务传播机制.docx

    当我们在使用 Spring 所提供的事务功能时,如果是仅仅处理单个的事务,是比较容易把握事务的提交与回滚,不过一旦引入嵌套事务后,多个事务的回滚和提交就会变得复杂起来,各个事务之间是如何相互影响的,是一个值得...

    Spring事务操作示例(四种方式)

    Spring事务操作示例(四种方式),包含完整代码和数据库文件(基于MySQL,在项目sql文件夹中),可运行,学习Spring事务详见博客:http://blog.csdn.net/daijin888888/article/details/51822257

    Spring事务传播Demo.zip

    本篇将基于"Spring事务传播Demo"来深入探讨Spring事务管理和传播行为。 首先,我们需要理解什么是事务。在数据库操作中,事务是一组操作,这些操作要么全部执行,要么全部不执行,以确保数据的一致性和完整性。在...

    spring事务,xml方式和注解方式

    Spring事务管理是Spring框架的核心特性之一,主要用于处理应用程序中的数据一致性问题。在多线程、分布式系统中,事务管理显得尤为重要。本节将详细介绍Spring如何通过XML配置和注解方式来实现事务管理。 首先,...

    spring事务详解

    Spring事务详解 Spring框架的事务管理功能是Java企业级开发中的重要组成部分,它将事务管理从具体的业务逻辑和数据访问逻辑中独立出来,实现了关注点分离。这种分离不仅降低了事务管理的复杂性,而且增强了代码的可...

Global site tag (gtag.js) - Google Analytics