spring中声明式事务实现原理猜想

@transactional注解简介 @transactional是spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚。@transactional注解可以帮助我们把事务开启、提交或者回滚的操作,通过aop的方式进行管理。
通过@transactional注解就能让spring为我们管理事务,免去了重复的事务管理逻辑,减少对业务代码的侵入,使我们开发人员能够专注于业务层面开发。
  我们知道实现@transactional原理是基于spring aop,aop又是动态代理模式的实现,通过对源码的阅读,总结出下面的步骤来了解实际中,在spring 是如何利用aop来实现@transactional的功能的。
spring中声明式事务实现原理猜想 首先,对于spring中aop实现原理有了解的话,应该知道想要对一个方法进行代理的话,肯定需要定义切点。在@transactional的实现中,同样如此,spring为我们定义了以 @transactional 注解为植入点的切点,这样才能知道@transactional注解标注的方法需要被代理。
有了切面定义之后,在spring的bean的初始化过程中,就需要对实例化的bean进行代理,并且生成代理对象。
生成代理对象的代理逻辑中,进行方法调用时,需要先获取切面逻辑,@transactional注解的切面逻辑类似于@around,在spring中是实现一种类似代理逻辑。
  @transactional作用 根据上面的原理猜想,下面简单介绍每个步骤的源码以进行验证。
首先是@transactional,作用是定义代理植入点。我们知道代理对象创建的通过beanpostprocessor的实现类annotationawareaspectjautoproxycreator的postprocessafterinstantiation方法来实现个,如果需要进行代理,那么在这个方法就会返回一个代理对象给容器,同时判断植入点也是在这个方法中。
那么下面开始分析,在配置好注解驱动方式的事务管理之后,spring会在ioc容器创建一个beanfactorytransactionattributesourceadvisor实例,这个实例可以看作是一个切点,在判断一个bean在初始化过程中是否需要创建代理对象,都需要验证一次beanfactorytransactionattributesourceadvisor是否是适用这个bean的切点。如果是,就需要创建代理对象,并且把beanfactorytransactionattributesourceadvisor实例注入到代理对象中。
前文我们知道在aoputils#findadvisorsthatcanapply中判断切面是否适用当前bean,可以在这个地方断点分析调用堆栈,aoputils#findadvisorsthatcanapply一致调用,最终通过以下代码判断是否适用切点。
abstractfallbacktransactionattributesource#computetransactionattribute(method method, class targetclass) 这里可以根据参数打上条件断点进行调试分析调用栈,targetclass就是目标class …一系列调用 最终springtransactionannotationparser#parsetransactionannotation(java.lang.reflect.annotatedelement) @overridepublic transactionattribute parsetransactionannotation(annotatedelement ae) {    //这里就是分析method是否被@transactional注解标注,有的话,不用说beanfactorytransactionattributesourceadvisor适配当前bean,进行代理,并且注入切点    //beanfactorytransactionattributesourceadvisor   annotationattributes attributes = annotatedelementutils.getmergedannotationattributes(ae, transactional.class);   if (attributes != null) {      return parsetransactionannotation(attributes);   }   else {      return null;   }} 上面就是判断是否需要根据@transactional进行代理对象创建的判断过程。@transactional的作用一个就是标识方法需要被代理,一个就是携带事务管理需要的一些属性信息。
动态代理逻辑实现 【aop实现原理分析】中知道,aop最终的代理对象的代理方法是
dynamicadvisedinterceptor#intercept 所以我们可以在这个方法断点分析代理逻辑。往期的面试题,点击查看。
@overridepublic object intercept(object proxy, method method, object[] args, methodproxy methodproxy) throws throwable {   object oldproxy = null;   boolean setproxycontext = false;   class targetclass = null;   object target = null;   try {      if (this.advised.exposeproxy) {         // make invocation available if necessary.         oldproxy = aopcontext.setcurrentproxy(proxy);         setproxycontext = true;      }      // may be null. get as late as possible to minimize the time we      // own the target, in case it comes from a pool...      target = gettarget();      if (target != null) {         targetclass = target.getclass();      }       //follow      list chain = this.advised.getinterceptorsanddynamicinterceptionadvice(method, targetclass);      object retval;      // check whether we only have one invokerinterceptor: that is,      // no real advice, but just reflective invocation of the target.      if (chain.isempty() && modifier.ispublic(method.getmodifiers())) {         // we can skip creating a methodinvocation: just invoke the target directly.         // note that the final invoker must be an invokerinterceptor, so we know         // it does nothing but a reflective operation on the target, and no hot         // swapping or fancy proxying.         object[] argstouse = aopproxyutils.adaptargumentsifnecessary(method, args);         retval = methodproxy.invoke(target, argstouse);      }      else {         // we need to create a method invocation...         retval = new cglibmethodinvocation(proxy, target, method, args, targetclass, chain, methodproxy).proceed();      }      retval = processreturntype(proxy, target, method, retval);      return retval;   }   finally {      if (target != null) {         releasetarget(target);      }      if (setproxycontext) {         // restore old proxy.         aopcontext.setcurrentproxy(oldproxy);      }   }} 通过分析 list chain = this.advised.getinterceptorsanddynamicinterceptionadvice(method, targetclass)返回的是transactioninterceptor,利用transactioninterceptor是如何实现代理逻辑调用的?
跟踪new cglibmethodinvocation(proxy, target, method, args, targetclass, chain, methodproxy).proceed();
发现最终是调用transactioninterceptor#invoke方法,并且把cglibmethodinvocation注入到invoke方法中,从上面可以看到cglibmethodinvocation是包装了目标对象的方法调用的所有必须信息,因此,在transactioninterceptor#invoke里面也是可以调用目标方法的,并且还可以实现类似@around的逻辑,在目标方法调用前后继续注入一些其他逻辑,比如事务管理逻辑。
transactioninterceptor–最终事务管理者 下面看代码。
transactioninterceptor#invoke @overridepublic object invoke(final methodinvocation invocation) throws throwable { // work out the target class: may be {@code null}. // the transactionattributesource should be passed the target class // as well as the method, which may be from an interface. class targetclass = (invocation.getthis() != null ? aoputils.gettargetclass(invocation.getthis()) : null); // adapt to transactionaspectsupport's invokewithintransaction... return invokewithintransaction(invocation.getmethod(), targetclass, new invocationcallback() {  @override  public object proceedwithinvocation() throws throwable {   return invocation.proceed();  } });} 继续跟踪invokewithintransaction,下面的代码中其实就可以看出一些逻辑端倪,就是我们猜想的实现方式,事务管理。
protected object invokewithintransaction(method method, class targetclass, final invocationcallback invocation)      throws throwable {   // if the transaction attribute is null, the method is non-transactional.   final transactionattribute txattr = gettransactionattributesource().gettransactionattribute(method, targetclass);   final platformtransactionmanager tm = determinetransactionmanager(txattr);   final string joinpointidentification = methodidentification(method, targetclass);   if (txattr == null || !(tm instanceof callbackpreferringplatformtransactionmanager)) {      // standard transaction demarcation with gettransaction and commit/rollback calls.       //开启事务      transactioninfo txinfo = createtransactionifnecessary(tm, txattr, joinpointidentification);      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.proceedwithinvocation();      }      catch (throwable ex) {         // target invocation exception     //回滚事务         completetransactionafterthrowing(txinfo, ex);         throw ex;      }      finally {         cleanuptransactioninfo(txinfo);      }       //提交事务      committransactionafterreturning(txinfo);      return retval;   }   else {      // it's a callbackpreferringplatformtransactionmanager: pass a transactioncallback in.      try {         object result = ((callbackpreferringplatformtransactionmanager) tm).execute(txattr,               new transactioncallback() {                  @override                  public object dointransaction(transactionstatus status) {                     transactioninfo txinfo = preparetransactioninfo(tm, txattr, joinpointidentification, status);                     try {                        return invocation.proceedwithinvocation();                     }                     catch (throwable ex) {                        if (txattr.rollbackon(ex)) {                           // a runtimeexception: will lead to a rollback.                           if (ex instanceof runtimeexception) {                              throw (runtimeexception) ex;                           }                           else {                              throw new throwableholderexception(ex);                           }                        }                        else {                           // a normal return value: will lead to a commit.                           return new throwableholder(ex);                        }                     }                     finally {                        cleanuptransactioninfo(txinfo);                     }                  }               });         // check result: it might indicate a throwable to rethrow.         if (result instanceof throwableholder) {            throw ((throwableholder) result).getthrowable();         }         else {            return result;         }      }      catch (throwableholderexception ex) {         throw ex.getcause();      }   }} 总结 最终可以总结一下整个流程,跟开始的猜想对照。
来源:blog.csdn.net/qq_20597727/article/details/84868035

台湾指控大陆猎取科技秘密,遭大陆有意针对
充电桩网络安全风险分析与措施
网管型交换机的特征和配置步骤
有哪些高性价比的蓝牙耳机,降噪蓝牙耳机选这些
麒麟9000s的4g和5g性能有区别
spring中声明式事务实现原理猜想
便携式湿度计的实际电路
CSR无线技术的“整合”策略
Amass 单PIN连接器:共享换电电池维护的高效利器
SysTools MDF Viewer Pro的主要功能列表
谈谈那些逐渐消失的编程语言
中科院入局光刻机 ASML相关的弊端也逐渐暴露
到2035年,纯电动汽车将成为新销售车辆的主流
航天宏图获得广西第二届人工智能大赛一等奖
四川省将采取多种措施加快推进5G基站建设
IBM陈旭东:打造AI核心竞争力,企业需要解决三大挑战
华为p50e是5g吗
DTAS尺寸公差分析与尺寸链计算软件&手机装配案例
中国智能座舱SoC芯片占据全球38%市场规模
LG宣布将于MWC2019推出旗下首款5G旗舰 将搭载高通骁龙855