在spring3 中如果使用了事务注解,那么如何调用生成的AopProxy代理对象中被代理对象的业务方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在spring3 中如果使用了事务注解,那么如何调用生成的AopProxy代理对象中被代理对象的业务方法?相关的知识,希望对你有一定的参考价值。

在现在的spring结构中,如果使用了事务等注解,那么其业务对象就会被代理。
现在的问题是,如果我们使用反射机制来动态调用这些业务对象中的方法,那么如何才能既保证其原有的spring特性,又能实现动态调用呢?
比如:通过动态获取到的对象名,用getBean获取该对象。
Object service=((ApplicationContext)appcontext).getBean(objName);
这里获取到的并不是我们需要的那个业务对象,而是已经被AOP代理的对象
所以使用普通的反射机制
Method method=service.getClass().getMethod(methodName, parameterTypes);
这里是根本得不到需要执行的方法。
所以在这里想问下大家,在得到这个AOP代理对象后,如何才能才能的到我们需要的方法并执行它。
我想这个肯定得看spring AOP代理这部分源码的! 不知道大家谁有看过没?给个指导意见,吸取下大家的智慧哈!
补充下:上面的那个业务对象“objName”对应的类是被@Transactional标注过的

参考技术A 将getBean得到的service强制转换成你的实现类就行了

spring事务实现原理

实现原理

本质

如果你用过Spring AOP,那么理解注解事务就十分简单了。事务注解本质上实在事务方法加入一个Around切面,在方法开始前开始事务,在抛出异常后回滚事务。使用简单伪代码可以简单理解为

doWithTransaction(...){
    try{
        startTransaction();//开启事务
        originMehod();//原始方法调用
        commit();//事务提交
    }catch(exception ex){
        rollback()//事务回滚
    }
}

事务传播性

Spring transaction有各种事务传播性,归根到底就是当前是新开事务还是使用已有事务(或者是抛异常)。其实很简单,使用一个ThreadLocal来记录下当前事务状态(是否在事务中),改造一下上面的方法

doWithTransaction(...){
    Transaction transaction= getFromThreadLocal();
    Transaction curTransaction;
    if(如果不存在事务){
        curTransaction = newTransaction()
        curTransaction.startTransaction();//开启事务
        try{
            originMehod();//原始方法调用
        }catch(exception ex){
            curTransaction.rollback()//事务回滚
            throw ex
        }
        curTransaction.commit();//事务提交
    }else{
        if(不支持当前事务){
            oldTransaction = transaction 
            oldTransaction.suspend()//当前事务挂起
            curTransaction = newTransaction();
            curTransaction.startTransaction();//开启事务
            try{
                originMehod();//原始方法调用
            } catch(exception ex){
                curTransaction.rollback()//事务回滚
                throw ex
            }
            curTransaction.commit();//事务提交
            oldTransaction.resume()
        }else{
            //复用已有事务
            originMehod();//原始方法调用
        }
    }
}

指定事务回滚异常

其实就再catch住异常以后,判断下当前异常是否需要回滚。

try{
    originMehod();//原始方法调用
} catch(exception ex){
    if(事务满足回滚){
        curTransaction.rollback()//事务回滚
    }
    throw ex
}

上面伪代码虽然简单,但spring注解事务的基本原理基本就是这样

源码阅读相关类

事务管理类

PlatformTransactionManager(及其抽象AbstractPlatformTransactionManager),其实是TransactionInterceptor中的一个重要属性,主要功能是,创建一个事务,提交事务,回滚事务等操作。我们再配置spring的时候都会创建,例如常见的DataSourceTransactionManager,。

AOP切面类

TransactionInterceptor(及其父类TransactionAspectSupport)保存类当前线程的事务状态,TransactionInterceptor是在调用事务方法中实际进入的入口:

  1. 根据当前注解内容,选择事务管理器(PlatformTransactionManager)
  2. 会根据当前线程事务状态,是创建新事务还是使用已有事务。

以上是关于在spring3 中如果使用了事务注解,那么如何调用生成的AopProxy代理对象中被代理对象的业务方法?的主要内容,如果未能解决你的问题,请参考以下文章

Spring事务管理,使用@Transactional注解

Spring使用@Async注解

阿昌教你解决在SpringBoot同一个对象内,事务方法互调默认失效问题

阿昌教你解决在SpringBoot同一个对象内,事务方法互调默认失效问题

Spring3.0配置多个事务管理器(即操作多个数据源)的方法

在Spring3中使用注解(@Scheduled)创建计划任务