@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的实现类AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInstantiation办法来实现个,如果须要进行代理,那么在这个办法就会返回一个代理对象给容器,同时判断植入点也是在这个办法中。

那么上面开始剖析,在配置好注解驱动形式的事务管理之后,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的作用一个就是标识办法须要被代理,一个就是携带事务管理须要的一些属性信息。

举荐一个 Spring Boot 基础教程及实战示例:
https://github.com/javastacks...

动静代理逻辑实现

【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<Object> 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<Object> 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<Object>() {                  @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();      }   }}

总结

最终能够总结一下整个流程,跟开始的猜测对照。

剖析源码后对照

原文链接:https://blog.csdn.net/qq_2059...

版权申明:本文为CSDN博主「一撸向北」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2021最新版)

2.别在再满屏的 if/ else 了,试试策略模式,真香!!

3.卧槽!Java 中的 xx ≠ null 是什么新语法?

4.Spring Boot 2.5 重磅公布,光明模式太炸了!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!