经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Spring aop 如何通过获取代理对象实现事务切换
来源:jb51  时间:2021/7/19 15:33:03  对本文有异议

Spring aop 获取代理对象实现事务切换

在项目中,涉及到同一个类中一个方法调用另外一个方法,并且两个方法的事务不相关,

这里面涉及到一个事务切换的问题,一般的方法没问题,根据通过aop注解在方法上通过加注解标识,

答案是:

通过spring aop类里面的AopContext类获取当前类的代理对象,

这样就能切换对应的事务管理器了,具体做法如下:

(1).在applicationContext.xml文件中配置如下:

  1. <!-- 开启暴露Aop代理到ThreadLocal支持 -->
  2. <aop:aspectj-autoproxy expose-proxy="true"/>

(2).在需要切换的地方获取代理对象,

再调用对应的方法,如下:

  1. ((类名) AopContext.currentProxy()).方法();

(3).注意

这里需要被代理对象使用的方法必须是public类型的方法,不然获取不到代理对象,会报下面的错误:

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.

开启暴露AOP代理即可.

因为开启事务和事务回滚,实际这个过程是aop代理帮忙完成的,当调用一个方法时,它会先检查时候有事务,有则开启事务,

当调用本类的方法是,它并没有将其视为proxy调用,而是方法的直接调用,所以也就没有检查该方法是否含有事务这个过程,

那么本地方法调用的事务也就无效了。

获取代理bean的原始对象

  1. public class AopTargetUtil {
  2. /**
  3. * 获取 目标对象
  4. * @param proxy 代理对象
  5. * @return
  6. * @throws Exception
  7. */
  8. public static Object getTarget(Object proxy) throws Exception {
  9. if(!AopUtils.isAopProxy(proxy)) {
  10. return proxy;//不是代理对象
  11. }
  12. if(AopUtils.isJdkDynamicProxy(proxy)) {
  13. return getJdkDynamicProxyTargetObject(proxy);
  14. } else { //cglib
  15. return getCglibProxyTargetObject(proxy);
  16. }
  17. }
  18. private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
  19. Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
  20. h.setAccessible(true);
  21. Object dynamicAdvisedInterceptor = h.get(proxy);
  22. Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
  23. advised.setAccessible(true);
  24. Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
  25. return target;
  26. }
  27. private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
  28. Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
  29. h.setAccessible(true);
  30. AopProxy aopProxy = (AopProxy) h.get(proxy);
  31. Field advised = aopProxy.getClass().getDeclaredField("advised");
  32. advised.setAccessible(true);
  33. Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
  34. return target;
  35. }
  36. }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号