spring-aop以及事务的解析

63 阅读28分钟
  • 什么是aop,什么是spring aop?

    • aop是面向切面编程,是oop(面向对象编程)的补充;在传统的OOP编程中,逻辑是自上而下的,所以在这个过程会产生很多横行性的问题并散落在各个地方(比如权限校验,日志打印);aop就是为分散对象提供了一种公共行为的抽象,降低了代码的重复率以及降低了模块间的耦合;
    • spring aop是对aop编程的具体实现,是在程序运行阶段完成对方法的增强。主要原理通过动态代理的方式以及spring内置的一些BeanPostProcessor完成对方法的横切增强;spring aop也支持@AspectJ风格的编码支持,及借助了AspectJ包下的一些注解(@AspectJ也是aop的实现,主要在编译阶段完成aop增强。)
  • spring中的动态代理

    • spring aop支持两种动态代理,JDK动态代理,cglib动态代理字节码增强技术,spring对存在接口的bean采用jdk动态代理。在bean的生命周期中,通过BeanPostProcessor完成生成代理对象;
    • JDK动态代理只能对实现了的接口的类生成代理(内部利用反射机制实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理),是一种委托机制,创建对象效率高,执行效率比较低
    • cglib是针对类实现代理,主要是对指定类生成一个子类,覆盖其中的方法(利用ASM字节码增强技术,操作字节码,所以不能代理final修饰的类),是一种继承机制,创建效率低,执行效率更高
    • 静态AOP: 在编译阶段对源程序代码进行修改,生成了静态的AOP代理类,生成的.class文件是已经修改过了,比如Aspect静态AOP框架;
    • JDK动态代理

      • JDK动态代理会对接口中所有的方法进行代理增强
    public class JDKProxy implements InvocationHandler {
        private   Object targetObject;
    
        public Object newProxy(Object target){
            this.targetObject = target;
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //进行动态代理的增强处理
            print();
            return method.invoke(targetObject, args);
        }
    
        public void print(){
            System.out.println("JDK实现动态代理");
        }
    }
    
    • cglib动态代理

      • cglib动态代理可以通过设置Enhancer的CallbackFilters完成对不同方法进行拦截增强
    public class CglibProxy implements MethodInterceptor {
    
        private Object targetObject;
    
        public Object createProxyObject(Object targetObject){
            this.targetObject = targetObject;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetObject.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //代理增强方法
            check();
            return method.invoke(targetObject, args);
        }
        private void check() {
            System.out.println("检查权限:check()!");
        }
    }
    
  • spring aop重要的几个概念

    • AOP中相关的概念: Aspect(切面)JointPoint(连接点)Advice(通知)Pointcut(切入点)引入(Introduction),织入(Weaving)
      • Aspect(切面):切面是通知和切点的结合,被@Aspect修饰的类,主要包括:1.通知的内容即需要增强的业务逻辑实现;2:通知的时机-Before,AfterReturning,AfterThrowing,After,Around;3通知的目标,即需要通知执行的切点上的所有连接点上。
    • JointPoint(连接点):连接点表示应用执行过程中能够插入切面的一个点,是一个结果;在Spring AOP中,连接点总是方法的调用。
    • Pointcut(切入点):一组连接点的集合,可以对连接点进行分组。所以每一组就是一个切点。
      • 连接点的匹配规则,execution,within,this,target,args,@target,@args,@annotation,并且可以通过表达式组合,即利用上述的表达式通过逻辑运算,与,或,非,组合在一起。
      • execution 可以精确到某个类中的某个方法
      • within:只能精确到某个类
      • args: args表达式的作用是匹配指定参数类型和指定参数数量的方法,与包名和类名无关
      • this: 代理对象是否继承或实现了对应类
      • target: 目标对象是否继承或实现了对应接口,与this不一样的是二者关注的对象不同,一个是代理对象,一个是目标对象
    • Advice(通知): 通知描述了切面何时以及如何执行增强处理,在spring中 xml与注解版本中After与AfterReturning的执行时机有区别,注解版本中AfterReturning优先于After,但在xml中与定义通知的顺序有关;并且可以指定通知的优先顺序order与
      • @Before:在目标方法之前执行
      • @After:在目标方法之后执行
      • @Around:在目标方法前后执行
      • @AfterReturning:在目标方法返回执行
      • @AfterThrowing:在目标方法异常执行
    • 引入(Introduction): spring aop可以不再修改代码的情况下,让某个类实现某个接口,并指定接口的默认实现方法,允许我们向现有类添加新的方法或者属性;
    • 织入(Weaving): 将增强处理添加到目标对象,并创建一个被增强的对象,这过程就是织入;
  • spring aop流程解析

    • 在sping bean的生命周期中,执行initializeBean方法中会执行所有BeanPostProcessor的生命周期初始化的后置回调方法BeanPostProcessor.postProcessAfterInitialization方法;其中有一个BeanPostProcessor叫做AnnotationAwareAspectJAutoProxyCreator,完成了spring中的aop,注意所有的bean都会执行该方法;
    • 找到容器中所有的切面(遍历容器中所有的BeanDefition或单例池,是否存在@Aspect注解),并将切面中的通知方法,转换成Advisor列表;执行连接点匹配规则,spring底层复用了AspectJ的规则来过滤出作用在当前Bean的Advisor列表,然后进行排序(Order,PriorityOrder)排序;
    • 通过ProxyFactory代理工厂,设置对应的TargetResources对象,通过 DefaultAopProxyFactory.createAopProxy创建动态代理工厂(JdkDynamicAopProxy或ObjenesisCglibAopProxy),最后通过动态代理工厂对象,完成动态代理的对象的生成;
    • 代理对象执行对应的方法时,会调用JdkDynamicAopProxy中.invoke方法或者ObjenesisCglibAopProxy.DynamicAdvisedInterceptor内部类的intercept方法,判断过滤当前方法上的通知advice列表,形成责任链,来完成spring aop的增强逻辑
    • spring aop的通知adive逻辑实际是通过责任链模式完成各种通知的逻辑增强,当所有的责任链都执行完后,会执行目标对象的方法;
      • @Around注解对应AspectJAroundAdvice,他会执行对应的方法然后通过调用 ProceedingJoinPoint.proceed方法完成责任链的方法调用的传递;
      • @Before注解对应MethodBeforeAdviceInterceptor,他会优先调用BeforeAdvice前置通知后,在执行责任链的下一个Advice
      • @After注解对应AspectJAfterAdvice,会在finally代码块完成通知方法的调用
      • @AfterReturning注解对应AfterReturningAdviceInterceptor,他会先执行调用链的方法,然后执行通知方法
      • @AfterThrowing注解对应AspectJAfterThrowingAdvice会在catch异常块中执行具体的通知
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
       //spring aop 代理对象真正执行的方法
       Object oldProxy = null;
       boolean setProxyContext = false;
    
       TargetSource targetSource = this.advised.targetSource;
       Object target = null;
    
       try {
          if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
             // The target does not implement the equals(Object) method itself.
             return equals(args[0]);
          }
          else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
             // The target does not implement the hashCode() method itself.
             return hashCode();
          }
          else if (method.getDeclaringClass() == DecoratingProxy.class) {
             // There is only getDecoratedClass() declared -> dispatch to proxy config.
             return AopProxyUtils.ultimateTargetClass(this.advised);
          }
          else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
             // Service invocations on ProxyConfig with the proxy config...
             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
          }
    
          Object retVal;
    
          if (this.advised.exposeProxy) {
             // Make invocation available if necessary.
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
    
          // Get as late as possible to minimize the time we "own" the target,
          // in case it comes from a pool.
          //获取目标对象
          target = targetSource.getTarget();
          Class<?> targetClass = (target != null ? target.getClass() : null);
    
          // Get the interception chain for this method.
          //目标对象target(targetSource返回)的方法配置增强的advisor列表,并构建拦截器链chain
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
          // Check whether we have any advice. If we don't, we can fall back on direct
          // reflective invocation of the target, and avoid creating a MethodInvocation.
          if (chain.isEmpty()) {
             // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
          }
          else {
             // We need to create a method invocation...
             MethodInvocation invocation =
                   new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
             // Proceed to the joinpoint through the interceptor chain.
    
             //执行通知链上所有通知
             retVal = invocation.proceed();
          }
    
          // Massage return value if necessary.
          Class<?> returnType = method.getReturnType();
          if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
             // Special case: it returned "this" and the return type of the method
             // is type-compatible. Note that we can't help if the target sets
             // a reference to itself in another returned object.
             retVal = proxy;
          }
          else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
             throw new AopInvocationException(
                   "Null return value from advice does not match primitive return type for: " + method);
          }
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             // Must have come from TargetSource.
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
    

aop执行.png

  • spring中的默认的通知ExposeInvocationInterceptor

    • ExposeInvocationInterceptor拦截器的代码,执行invoke()方法的入参mi,其实就是ReflectiveMethodInvocation实例,而ReflectiveMethodInvocation中是包含了拦截器链,通过当前的ReflectiveMethodInvocation实例变量放入了ThreadLocal中,这样在同一个线程中,通过ThreadLocal来共享拦截器链
  • 自定义编码完成springaop

    public static void test(){
        ProxyFactory pf = new ProxyFactory();
        pf.setInterfaces(LogApi.class);
        pf.setTarget(new LogApiImpl());
        pf.addAdvice(new BeforeAdvice());
        LogApi proxy = (LogApi)pf.getProxy();
        proxy.printLog();
    
    }
    
    //手动实现了BeforeAdvice
    @Slf4j
    public class BeforeAdvice implements MethodInterceptor {
    
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        log.error("--------BeforeAdvice-----before");
        return methodInvocation.proceed();
    }
    }
    
  • spring aop源码解析

    • 执行postProcessAfterInitialization方法,调用wrapIfNecessary方法对增强类,创建代理对象;
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
      if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
         return bean;
      }
      if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
         return bean;
      }
      if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return bean;
      }
    
      // Create proxy if we have advice.
      //遍历容器中所有切面,过滤筛选作用在当前bean的advice列表
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
      if (specificInterceptors != DO_NOT_PROXY) {
         this.advisedBeans.put(cacheKey, Boolean.TRUE);
    
         //spring aop -创建代理工厂,spring aop代理对象是根据TargetSource有关,和目标对象无关
         Object proxy = createProxy(
               bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
         this.proxyTypes.put(cacheKey, proxy.getClass());
         return proxy;
      }
    
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
    }
    
    • 执行AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法查找容器中所有切面,并过滤筛选出作用在当前bean的adviceor列表(并进行排序)
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
       //获取容器中所有切面的Advisor,包括事务通知BeanFactoryTransactionAttributeSourceAdvisor
       List<Advisor> candidateAdvisors = findCandidateAdvisors();
    
       //过滤出作用在当前bean 上的Advisor列表(执行连接点的匹配规则,底层采用了aspectj包的匹配功能),注解版本的并完成排序
       List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    
       extendAdvisors(eligibleAdvisors);
       if (!eligibleAdvisors.isEmpty()) {
          //对Advisor进行排序,切面可以实现Ordered,PriorityOrder接口
          eligibleAdvisors = sortAdvisors(eligibleAdvisors);
       }
       return eligibleAdvisors;
    }
    
    • 调用BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors方法找到容器中所有的advice通知列表
    public List<Advisor> buildAspectJAdvisors() {
       List<String> aspectNames = this.aspectBeanNames;
    
       if (aspectNames == null) {
          synchronized (this) {
             aspectNames = this.aspectBeanNames;
             if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                //获取spring容器中所有的bean与beanDefinition的名称
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                      this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                   //判断是否为合格的bean
                   if (!isEligibleBean(beanName)) {
                      continue;
                   }
                   // We must be careful not to instantiate beans eagerly as in this case they
                   // would be cached by the Spring container but would not have been weaved.
                   Class<?> beanType = this.beanFactory.getType(beanName, false);
                   if (beanType == null) {
                      continue;
                   }
                   //判断当前bean是否是切面 被@Aspect注解
                   if (this.advisorFactory.isAspect(beanType)) {
                      aspectNames.add(beanName);
                      AspectMetadata amd = new AspectMetadata(beanType, beanName);
                      if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                         MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
    
                         //获取切面中所有的Advise通知的方法(会排除@Pontcut方法),并且转换成Advisor
                         List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
    
                         //判断是否为单例bean
                         if (this.beanFactory.isSingleton(beanName)) {
                            //设置缓存
                            this.advisorsCache.put(beanName, classAdvisors);
                         }
                         else {
                            //设置解析工厂对象缓存
                            this.aspectFactoryCache.put(beanName, factory);
                         }
                         advisors.addAll(classAdvisors);
                      }
                      else {
                         // Per target or per this.
                         if (this.beanFactory.isSingleton(beanName)) {
                            throw new IllegalArgumentException("Bean with name '" + beanName +
                                  "' is a singleton, but aspect instantiation model is not singleton");
                         }
                         MetadataAwareAspectInstanceFactory factory =
                               new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                         this.aspectFactoryCache.put(beanName, factory);
                         advisors.addAll(this.advisorFactory.getAdvisors(factory));
                      }
                   }
                }
                this.aspectBeanNames = aspectNames;
                return advisors;
             }
          }
       }
    
       if (aspectNames.isEmpty()) {
          return Collections.emptyList();
       }
       List<Advisor> advisors = new ArrayList<>();
       for (String aspectName : aspectNames) {
          List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
          if (cachedAdvisors != null) {
             advisors.addAll(cachedAdvisors);
          }
          else {
             MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
             advisors.addAll(this.advisorFactory.getAdvisors(factory));
          }
       }
       return advisors;
    }
    
    • 调用ReflectiveAspectJAdvisorFactory.getAdvisor方法判断是否添加了Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,并为通知方法构建advisor对象InstantiationModelAwarePointcutAdvisorImpl
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
          int declarationOrderInAspect, String aspectName) {
    
       validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    
       //private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
       //       Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
       //从增强方法获取切点信息,判断方法是否存在以上注解
       AspectJExpressionPointcut expressionPointcut = getPointcut(
             candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
       if (expressionPointcut == null) {
          return null;
       }
    
       //为增强方法构建Advisor对象
       return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
             this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }
    
    • 调用JdkDynamicAopProxy或CglibAopProxy的getProxy方法创建代理对象
    //JdkDynamicAopProxy.getProxy创建代理对象
    public Object getProxy(@Nullable ClassLoader classLoader) {
       if (logger.isTraceEnabled()) {
          logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
       }
       return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this);
    }
    
    //CglibAopProxy.getProxy,cglib实现动态代理
    public Object getProxy(@Nullable ClassLoader classLoader) {
       if (logger.isTraceEnabled()) {
          logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
       }
    
       try {
          Class<?> rootClass = this.advised.getTargetClass();
          Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    
          Class<?> proxySuperClass = rootClass;
          if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
             proxySuperClass = rootClass.getSuperclass();
             Class<?>[] additionalInterfaces = rootClass.getInterfaces();
             for (Class<?> additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
             }
          }
    
          // Validate the class, writing log messages as necessary.
          validateClassIfNecessary(proxySuperClass, classLoader);
    
          // Configure CGLIB Enhancer...
          Enhancer enhancer = createEnhancer();
          if (classLoader != null) {
             enhancer.setClassLoader(classLoader);
             if (classLoader instanceof SmartClassLoader &&
                   ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
             }
          }
          enhancer.setSuperclass(proxySuperClass);
          enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
          enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
          enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    
          //设置spring aop中方法的的增强执行
          Callback[] callbacks = getCallbacks(rootClass);
          Class<?>[] types = new Class<?>[callbacks.length];
          for (int x = 0; x < types.length; x++) {
             types[x] = callbacks[x].getClass();
          }
          // fixedInterceptorMap only populated at this point, after getCallbacks call above
          enhancer.setCallbackFilter(new ProxyCallbackFilter(
                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
          enhancer.setCallbackTypes(types);
    
          // Generate the proxy class and create a proxy instance.
          return createProxyClassAndInstance(enhancer, callbacks);
       }
       catch (CodeGenerationException | IllegalArgumentException ex) {
          throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                ": Common causes of this problem include using a final class or a non-visible class",
                ex);
       }
       catch (Throwable ex) {
          // TargetSource.getTarget() failed
          throw new AopConfigException("Unexpected AOP exception", ex);
       }
    }
    
    • 执行代理对象的方法,会执行对应的方法调用
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
       //spring aop 代理对象真正执行的方法
       Object oldProxy = null;
       boolean setProxyContext = false;
    
       TargetSource targetSource = this.advised.targetSource;
       Object target = null;
    
       try {
          if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
             // The target does not implement the equals(Object) method itself.
             return equals(args[0]);
          }
          else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
             // The target does not implement the hashCode() method itself.
             return hashCode();
          }
          else if (method.getDeclaringClass() == DecoratingProxy.class) {
             // There is only getDecoratedClass() declared -> dispatch to proxy config.
             return AopProxyUtils.ultimateTargetClass(this.advised);
          }
          else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
             // Service invocations on ProxyConfig with the proxy config...
             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
          }
    
          Object retVal;
    
          if (this.advised.exposeProxy) {
             // Make invocation available if necessary.
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
    
          // Get as late as possible to minimize the time we "own" the target,
          // in case it comes from a pool.
          //获取目标对象,目标对象是通过targetSource获取的,所以spring aop是和TargetSource有关
          target = targetSource.getTarget();
          Class<?> targetClass = (target != null ? target.getClass() : null);
    
          // Get the interception chain for this method.
          //目标对象target(targetSource返回)的方法配置增强的advisor列表,并构建拦截器链chain
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
          // Check whether we have any advice. If we don't, we can fall back on direct
          // reflective invocation of the target, and avoid creating a MethodInvocation.
          if (chain.isEmpty()) {
             // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
          }
          else {
             // We need to create a method invocation...
             MethodInvocation invocation =
                   new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
             // Proceed to the joinpoint through the interceptor chain.
    
             //执行通知链上所有通知
             retVal = invocation.proceed();
          }
    
          // Massage return value if necessary.
          Class<?> returnType = method.getReturnType();
          if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
             // Special case: it returned "this" and the return type of the method
             // is type-compatible. Note that we can't help if the target sets
             // a reference to itself in another returned object.
             retVal = proxy;
          }
          else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
             throw new AopInvocationException(
                   "Null return value from advice does not match primitive return type for: " + method);
          }
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             // Must have come from TargetSource.
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
    
    • spring aop通知执行的逻辑是通过ReflectiveMethodInvocation.proceed方法执行拦截器链,cglib会执行对应的Interceptor方法,然后通过DynamicAdvisedInterceptor对方法进行aop增强,获取过滤当前方法的advice列表,构建CglibMethodInvocation继承了ReflectiveMethodInvocation方法,来执行拦截器链上的链路执行,具体的流程是一样的;
    public Object proceed() throws Throwable {
       // We start with an index of -1 and increment early.
    
       //判断拦截器链是否已经全部执行
       if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
          //执行后目标对象的方法(通过反射)
          return invokeJoinpoint();
       }
    
       //依次获取拦截器链上的通知
       Object interceptorOrInterceptionAdvice =
             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
       if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
          // Evaluate dynamic method matcher here: static part will already have
          // been evaluated and found to match.
          InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
          Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
          if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
             return dm.interceptor.invoke(this);
          }
          else {
             // Dynamic matching failed.
             // Skip this interceptor and invoke the next in the chain.
             return proceed();
          }
       }
       else {
          // It's an interceptor, so we just invoke it: The pointcut will have
          // been evaluated statically before this object was constructed.
          //执行链上的通知
          return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
       }
    }
    
  • spring中事务

  • spring框架提供了事务管理的功能,允许用户定义事务的边界和行为等(定义事务的传播行为,隔离级别等),以确保数据的完整性和一致。spring提供了两种事务管理机制,声明式事务管理和编程式事务管理。spring声明事务管理是基于spring aop实现的;

    • 声明式事务管理
      • 基于注解@Transactional + @EnableTransactionManagement(开启事务管理)
      • 基于XML实现,在Spring的XML配置文件中,你可以使用<tx:advice><aop:config>标签来定义事务通知和切点
    • 编程事务管理
      • 使用TransactionTemplate管理事务,如果有返回值,采用TransactionCallback;如果没有返回值,采用TransactionCallbackWithoutResult
      • 使用PlatformTransactionManager管理事务
@Configuration
public class DataSourceConfiguration {


    /**
     * datasource:
     *     url:
     *     username: root
     *     password: 123456
     *     driverClassName: com.mysql.cj.jdbc.Driver
     * @return
     */
    @Bean
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setPassword("123456");
        dataSource.setUrl("");
        dataSource.setUsername("root");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(){
        return new JdbcTemplate(dataSource());
    }


    @Bean
    public PlatformTransactionManager transactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource());
        return dataSourceTransactionManager;
    }

    @Bean
    public TransactionTemplate transactionTemplate(){
        return new TransactionTemplate(transactionManager());
    }
}
/**
 * spring事务
 * <p>
 * 1。编程式事务管理
 * <p>
 * 2。声明式事务管理
 */
@Slf4j
@Component("SpringTransaction")
@EnableTransactionManagement
public class SpringTransaction {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    /**
     * 使用TransactionTemplate,实现编程式事务
     * 1.如果有返回值,采用TransactionCallback;
     * 2.如果没有返回值,采用TransactionCallbackWithoutResult;
     */
    public void testTransactionTemplate() {

        Integer count = transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    return testUpdate("testTransactionTemplate");
                } catch (Exception e) {
                    log.error("testTransactionTemplate异常{}", e.getMessage(), e);
                    transactionStatus.setRollbackOnly();
                    return -1;
                }
            }
        });

        log.info("testTransactionTemplate执行结果:{}", count);
    }





    /**
     * 利用PlatformTransactionManager完成编程式事务
     * 1.定义事务配置(事务隔离级别,传播级别,事务名称等),通过PlatformTransactionManager获取事务状态TransactionStatus
     * 主要通过对应的TransactionManager获取对应的ConnectionHolder,并将TransactionSynchronizationManager事务同步管理器,
     *
     *
     */
    public void testPlatformTransactionManager() {
        DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        transactionDefinition.setName("testPlatformTransactionManager");
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        Integer count = null;
        try {
            count = testUpdateWithPropagation("testPlatformTransactionManager.testUpdateWithPropagation");
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            log.error("testTransactionTemplate异常{}", e.getMessage(), e);
            transactionManager.rollback(transactionStatus);
        }
        log.info("testPlatformTransactionManager执行结果:{}", count);
    }

    public int testUpdateWithPropagation(String message) {
        DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        transactionDefinition.setName("testUpdateWithPropagation");
        transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        try {
            int count = jdbcTemplate.update("update  t_cu_wyr_bank set core_cust_id = '" + message + "' where core_mer_no = 'myId1711190640426'");
            log.info("更新条数:{}", count);
            transactionManager.commit(transactionStatus);
            //int i = 1/0;
            return count;
        } catch (Exception e) {
            log.error("testUpdateWithPropagation{}", e.getMessage(), e);
            transactionManager.rollback(transactionStatus);
            return -1;
        }

    }


    /**
     * ProxyTransactionManagementConfiguration
     * <p>
     * org.springframework.transaction.config.internalTransactionAdvisor   ------> BeanFactoryTransactionAttributeSourceAdvisor
     * <p>
     * TransactionAttributeSourcePointcut的内部类TransactionAttributeSourceClassFilter.match方法匹配bean上的每个方法,
     * 采用SpringTransactionAnnotationParser.isCandidateClass方法是否添加了@Transactional注解
     * <p>
     * <p>
     * TransactionInterceptor 执行事务增强逻辑
     *
     *
     *
     * TransactionSynchronizationManager spring中管理事务同步的核心类,主要通过TreadLocal来进行不同线程之间的数据隔离,以及相同线程之间的事务同步共享
     * 它负责管理每个线程的数据库连接资源和事务同步,确保事务在多线程环境下的正确执行
     *
     * @EnableTransactionManagement开启spring注解声明式事务;
     * @Transactional 事务注解
     */
    @Transactional
    public void testTransactionalAnnotation() {
        testUpdate("testTransactionalAnnotation222222");
    }


    public int testUpdate(String message) {
        int count = jdbcTemplate.update("update  t_cu_wyr_bank set core_cust_id = '" + message + "' where core_mer_no = 'myId1711190640426'");
        log.info("更新条数:{}", count);
        //int i = 1/0;
        return count;
    }


}
  • spring事务解析流程

spring-事务流程解析.png

  • spring自定义事务流程解析

    • spring事务是基于spring aop来实现的。所以当@EnableTransactionManagement开启事务时, @Import({TransactionManagementConfigurationSelector.class})在spring扫描的时候,会将TransactionManagementConfigurationSelector作为一个配置类注册到单例池中,由于它实现了ImportSelector,所以会调用其的selectImports方法,向容器中注册BeanFactoryTransactionAttributeSourceAdvisor对象以及TransactionInterceptor对象
    @Configuration(
        proxyBeanMethods = false
    )
    @Role(2)
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
        public ProxyTransactionManagementConfiguration() {
        }
    
        @Bean(
            name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
        )
        @Role(2)
        public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            advisor.setTransactionAttributeSource(transactionAttributeSource);
            advisor.setAdvice(transactionInterceptor);
            if (this.enableTx != null) {
                advisor.setOrder((Integer)this.enableTx.getNumber("order"));
            }
    
            return advisor;
        }
    
        @Bean
        @Role(2)
        public TransactionAttributeSource transactionAttributeSource() {
            return new AnnotationTransactionAttributeSource();
        }
    
        @Bean
        @Role(2)
        public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
            TransactionInterceptor interceptor = new TransactionInterceptor();
            interceptor.setTransactionAttributeSource(transactionAttributeSource);
            if (this.txManager != null) {
                interceptor.setTransactionManager(this.txManager);
            }
    
            return interceptor;
        }
    }
    
    • 当spring在bean的生命周期中,执行spring aop的AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization的方法时,去筛选对应的;因为spring的扫描时机在bean的生命周期之前完成的。所以在advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false)会将BeanFactoryTransactionAttributeSourceAdvisor加到Advisor列表中;
    /**
     * Find all candidate Advisors to use in auto-proxying.
     * @return the List of candidate Advisors
     */
    protected List<Advisor> findCandidateAdvisors() {
       Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    
       //当spring采用了声明式事务的话,会有一个BeanFactoryTransactionAttributeSourceAdvisor
       return this.advisorRetrievalHelper.findAdvisorBeans();
    }
    
    
    
    public List<Advisor> findAdvisorBeans() {
       // Determine list of advisor bean names, if not cached already.
       String[] advisorNames = this.cachedAdvisorBeanNames;
       if (advisorNames == null) {
          // Do not initialize FactoryBeans here: We need to leave all regular beans
          // uninitialized to let the auto-proxy creator apply to them!
          advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
          this.cachedAdvisorBeanNames = advisorNames;
       }
       if (advisorNames.length == 0) {
          return new ArrayList<>();
       }
    
       List<Advisor> advisors = new ArrayList<>();
       for (String name : advisorNames) {
          if (isEligibleBean(name)) {
             if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                   logger.trace("Skipping currently created advisor '" + name + "'");
                }
             }
             else {
                try {
                   advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                   Throwable rootCause = ex.getMostSpecificCause();
                   if (rootCause instanceof BeanCurrentlyInCreationException) {
                      BeanCreationException bce = (BeanCreationException) rootCause;
                      String bceBeanName = bce.getBeanName();
                      if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                         if (logger.isTraceEnabled()) {
                            logger.trace("Skipping advisor '" + name +
                                  "' with dependency on currently created bean: " + ex.getMessage());
                         }
                         // Ignore: indicates a reference back to the bean we're trying to advise.
                         // We want to find advisors other than the currently created bean itself.
                         continue;
                      }
                   }
                   throw ex;
                }
             }
          }
       }
       return advisors;
    }
    
    • 在执行AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply筛选过滤作用在当前bean的List列表,最终调用到AopUtils.canApply方法判断该Advisor是否作用到当前bean上; 在类级别过滤筛选时,最终会调用SpringTransactionAnnotationParser.isCandidateClass方法,判断类上是否添加@Transactional注解在方法级别过滤时,调用TransactionAttributeSourcePointcut.matchs方法,最终调用 AnnotationTransactionAttributeSource.getTransactionAttribute方法判断方法是否添加@Transactional注解
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
       Assert.notNull(pc, "Pointcut must not be null");
    
       //先在类级别进行匹配,如果不匹配,那么直接返回false
       if (!pc.getClassFilter().matches(targetClass)) {
          return false;
       }
    
       MethodMatcher methodMatcher = pc.getMethodMatcher();
       if (methodMatcher == MethodMatcher.TRUE) {
          // No need to iterate the methods if we're matching any method anyway...
          return true;
       }
    
       IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
       if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
          introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
       }
    
       Set<Class<?>> classes = new LinkedHashSet<>();
       if (!Proxy.isProxyClass(targetClass)) {
          classes.add(ClassUtils.getUserClass(targetClass));
       }
       classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    
       //遍历处理目标类和目标类的接口
       for (Class<?> clazz : classes) {
          Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
          for (Method method : methods) {
             //
             if (introductionAwareMethodMatcher != null ?
                   introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                   methodMatcher.matches(method, targetClass)) {
                return true;
             }
          }
       }
    
       return false;
    }
    
    
    public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
       if (method.getDeclaringClass() == Object.class) {
          return null;
       }
    
       // First, see if we have a cached value.
       Object cacheKey = getCacheKey(method, targetClass);
       TransactionAttribute cached = this.attributeCache.get(cacheKey);
       if (cached != null) {
          // Value will either be canonical value indicating there is no transaction attribute,
          // or an actual transaction attribute.
          if (cached == NULL_TRANSACTION_ATTRIBUTE) {
             return null;
          }
          else {
             return cached;
          }
       }
       else {
          // We need to work it out.
          TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
          // Put it in the cache.
          if (txAttr == null) {
             this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
          }
          else {
             String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
             if (txAttr instanceof DefaultTransactionAttribute) {
                DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;
                dta.setDescriptor(methodIdentification);
                dta.resolveAttributeStrings(this.embeddedValueResolver);
             }
             if (logger.isTraceEnabled()) {
                logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
             }
             this.attributeCache.put(cacheKey, txAttr);
          }
          return txAttr;
       }
    }
    
    
    • 执行代理方法时完成spring事务增强,TransactionInterceptor.invoke完成声明式事务管理
    public Object invoke(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);
    
       //传入一个回调函数,让advice通知责任链继续执行
       return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
          @Override
          @Nullable
          public Object proceedWithInvocation() throws Throwable {
             return invocation.proceed();
          }
          @Override
          public Object getTarget() {
             return invocation.getThis();
          }
          @Override
          public Object[] getArguments() {
             return invocation.getArguments();
          }
       });
    }
    
    • 执行编程式事务PlatformTransactionManager执行流程,创建TransactionInfo事务对象信息后,继续执行拦截器链上的通知以及目标方法后,出现异常调用completeTransactionAfterThrowing进行事务回滚或提交;执行commitTransactionAfterReturning进行事务提交;
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
          final InvocationCallback invocation) throws Throwable {
    
       // If the transaction attribute is null, the method is non-transactional.
       //获取TransactionAttributeSource对象,用于从类或者方法上事务注解分析相应的事务属性,如果是注解版本AnnotationTransactionAttributeSource对象
       TransactionAttributeSource tas = getTransactionAttributeSource();
    
       //获取方法或类上获取事务属性信息(事务回滚策略,事务传播机制,隔离级别等)---RuleBasedTransactionAttribute
       final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    
       //获取TransactionManager事务管理对象,
       final TransactionManager tm = determineTransactionManager(txAttr);
    
       //spring 5.2版本引入的反应式事务编程管理,主要用于异步处理
       if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
          boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
          boolean hasSuspendingFlowReturnType = isSuspendingFunction &&
                COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
          if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
             throw new IllegalStateException("Coroutines invocation not supported: " + method);
          }
          CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);
    
          ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
             Class<?> reactiveType =
                   (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
             ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
             if (adapter == null) {
                throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type [" +
                      method.getReturnType() + "] with specified transaction manager: " + tm);
             }
             return new ReactiveTransactionSupport(adapter);
          });
    
          InvocationCallback callback = invocation;
          if (corInv != null) {
             callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
          }
          Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
          if (corInv != null) {
             Publisher<?> pr = (Publisher<?>) result;
             return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) :
                   KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
          }
          return result;
       }
    
       //将编程式事务管理器PlatformTransactionManager
       PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
       final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    
       if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
          // Standard transaction demarcation with getTransaction and commit/rollback calls.
    
          //
          TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
    
          Object retVal;
          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);
          }
    
          if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
             // Set rollback-only in case of Vavr failure matching our rollback rules...
             TransactionStatus status = txInfo.getTransactionStatus();
             if (status != null && txAttr != null) {
                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
             }
          }
          //事务提交
          commitTransactionAfterReturning(txInfo);
          return retVal;
       }
    
       else {
          Object result;
          final ThrowableHolder throwableHolder = new ThrowableHolder();
    
          //CallbackPreferringPlatformTransactionManager,通过回调(Callback)来处理事务,比较依赖回调方法;
          // 事务管理策略和代码逻辑与回调机制相协调
          // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
          try {
             result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                try {
                   Object retVal = invocation.proceedWithInvocation();
                   if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                      // Set rollback-only in case of Vavr failure matching our rollback rules...
                      retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                   }
                   return retVal;
                }
                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.
                      throwableHolder.throwable = ex;
                      return null;
                   }
                }
                finally {
                   cleanupTransactionInfo(txInfo);
                }
             });
          }
          catch (ThrowableHolderException ex) {
             throw ex.getCause();
          }
          catch (TransactionSystemException ex2) {
             if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
             }
             throw ex2;
          }
          catch (Throwable ex2) {
             if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
             }
             throw ex2;
          }
    
          // Check result state: It might indicate a Throwable to rethrow.
          if (throwableHolder.throwable != null) {
             throw throwableHolder.throwable;
          }
          return result;
       }
    }
    
    • PlatformTransactionManager.getTransaction获取事务状态信息DefaultTransactionStatus; 构建对应的TransactionInfo对象(它持有事务的状态信息,事务嵌套关系,以及事务的调用链表oldTransactionInfo<链表的头指针>)与当前线程绑定;
    /**
     * 获取当前事务状态TransactionStatus
     *
     * 1.获取当前事务的ConnectionHolder链接对象
     * 2.事务的传播属性验证(传播属性规则)
     * 2.1 若存在事务时,判断事务传播属性,判断是否抛异常,是否需要挂起当前事务后(创建新事物或非事务运行),是否支持嵌套事务(创建事务保存点),或者加入当前事务或者以非事务执行
     * 2.2 若创建新事务时,隔离级别,timeout ,ConnectionHolder等配置并绑定到当前线程
    
     */
    @Override
    public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
          throws TransactionException {
    
       // Use defaults if no transaction definition given.
       TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
    
       //获取当前线程缓存在threadLocal里面的ConnectionHolder, 如果没有 ,DataSourceTransactionObject里的ConnectionHolder为null
       Object transaction = doGetTransaction();
    
       boolean debugEnabled = logger.isDebugEnabled();
    
       //判断当前是否存在事务,当前DataSourceTransactionObject里的ConnectionHolder不为空且transactionActive为true
       if (isExistingTransaction(transaction)) {
          // Existing transaction found -> check propagation behavior to find out how to behave.
          return handleExistingTransaction(def, transaction, debugEnabled);
       }
    
       // Check definition settings for new transaction.
       //事务的超时设置验证
       if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
          throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
       }
    
       // No existing transaction found -> check propagation behavior to find out how to proceed.
       //当前事务传播机制为TransactionDefinition.PROPAGATION_MANDATORY==2;但当前没有事务,所以抛出异常
       if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
          throw new IllegalTransactionStateException(
                "No existing transaction found for transaction marked with propagation 'mandatory'");
       }
       //当前不存在事务,创建新的事务执行
       else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
             def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
             def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
    
          //事务挂起,传null,不会做任何操作
          SuspendedResourcesHolder suspendedResources = suspend(null);
          if (debugEnabled) {
             logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
          }
          try {
             //创建一个新的事务
             return startTransaction(def, transaction, debugEnabled, suspendedResources);
          }
          catch (RuntimeException | Error ex) {
             resume(null, suspendedResources);
             throw ex;
          }
       }
       else {
          // Create "empty" transaction: no actual transaction, but potentially synchronization.
          //以非事务方式执行,但隔离级别不为默认,会抛出一个warn日志
          if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
             logger.warn("Custom isolation level specified but no actual transaction initiated; " +
                   "isolation level will effectively be ignored: " + def);
          }
          boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
          return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
       }
    }
    
    private TransactionStatus handleExistingTransaction(
          TransactionDefinition definition, Object transaction, boolean debugEnabled)
          throws TransactionException {
    
       //当前存在事务,但是传播属性PROPAGATION_NEVER  所以会抛异常
       if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
          throw new IllegalTransactionStateException(
                "Existing transaction found for transaction marked with propagation 'never'");
       }
    
       if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
          if (debugEnabled) {
             logger.debug("Suspending current transaction");
          }
          //当前存在事务,挂起当前事务-suspendedResources = SuspendedResourcesHolder
          Object suspendedResources = suspend(transaction);
          boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
          //并以非事务运行
          return prepareTransactionStatus(
                definition, null, false, newSynchronization, debugEnabled, suspendedResources);
       }
    
       if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
          if (debugEnabled) {
             logger.debug("Suspending current transaction, creating new transaction with name [" +
                   definition.getName() + "]");
          }
          //当前存在事务,挂起当前事务
          SuspendedResourcesHolder suspendedResources = suspend(transaction);
          try {
             //创建一个新的事务运行
             return startTransaction(definition, transaction, debugEnabled, suspendedResources);
          }
          catch (RuntimeException | Error beginEx) {
             resumeAfterBeginException(transaction, suspendedResources, beginEx);
             throw beginEx;
          }
       }
    
       if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
          if (!isNestedTransactionAllowed()) {
             throw new NestedTransactionNotSupportedException(
                   "Transaction manager does not allow nested transactions by default - " +
                   "specify 'nestedTransactionAllowed' property with value 'true'");
          }
          if (debugEnabled) {
             logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
          }
          if (useSavepointForNestedTransaction()) {
             // Create savepoint within existing Spring-managed transaction,
             // through the SavepointManager API implemented by TransactionStatus.
             // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
    
             //transaction  DataSourceTransactionObject
             DefaultTransactionStatus status =
                   prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
    
             //创建事务保存点-----底层通过transaction(DataSourceTransactionObject)中的ConnectionHolder的
             //Connection去创建保存点(底层是JDBC的封装)
             status.createAndHoldSavepoint();
             return status;
          }
          else {
             // Nested transaction through nested begin and commit/rollback calls.
             // Usually only for JTA: Spring synchronization might get activated here
             // in case of a pre-existing JTA transaction.
    
             return startTransaction(definition, transaction, debugEnabled, null);
          }
       }
    
       // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
       if (debugEnabled) {
          logger.debug("Participating in existing transaction");
       }
       if (isValidateExistingTransaction()) {
    
          //判断隔离级别非默认
          if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
             Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
             if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
                Constants isoConstants = DefaultTransactionDefinition.constants;
                throw new IllegalTransactionStateException("Participating transaction with definition [" +
                      definition + "] specifies isolation level which is incompatible with existing transaction: " +
                      (currentIsolationLevel != null ?
                            isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
                            "(unknown)"));
             }
          }
          if (!definition.isReadOnly()) {
             if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                throw new IllegalTransactionStateException("Participating transaction with definition [" +
                      definition + "] is not marked as read-only but existing transaction is");
             }
          }
       }
       boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    
       //当前存在事务,则加入事务
       return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
    }
    
    • 事务提交与回滚

    • 事务的提交与回滚都是JDBC的connection来进行事务提交和回滚
    
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
       try {
          boolean beforeCompletionInvoked = false;
    
          try {
             boolean unexpectedRollback = false;
    
             //用于在事务提交之前进行准备工作和触发前置回调-在事务提交之前进行准备工作,如资源锁定、日志记录等1
             //扩展方法
             prepareForCommit(status);
    
             //扩展机制
             triggerBeforeCommit(status);
    
             //扩展机制
             triggerBeforeCompletion(status);
    
             beforeCompletionInvoked = true;
    
             //当前事务提交的时候,存在事务保存点(嵌套事务),则释放保存点,无须提交事务
             if (status.hasSavepoint()) {
                if (status.isDebug()) {
                   logger.debug("Releasing transaction savepoint");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
                //释放持有的回滚点
                status.releaseHeldSavepoint();
             }
             //新的事务,调用子类doCommit提交事务
             else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                   logger.debug("Initiating transaction commit");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
    
                //提交事务-DataSourceTransactionManager,
                //获取DefaultTransactionStatus中的DataSourceTransactionObject中ConnectionHolder中的Connection去提交事务
                doCommit(status);
             }
             else if (isFailEarlyOnGlobalRollbackOnly()) {
                unexpectedRollback = status.isGlobalRollbackOnly();
             }
    
             // Throw UnexpectedRollbackException if we have a global rollback-only
             // marker but still didn't get a corresponding exception from commit.
             //判断是否标记了 全局回滚,RollbackOnly=true(当前的ConnectionHolder的RollbackOnly属性)
             if (unexpectedRollback) {
                throw new UnexpectedRollbackException(
                      "Transaction silently rolled back because it has been marked as rollback-only");
             }
          }
          catch (UnexpectedRollbackException ex) {
             // can only be caused by doCommit
             //事务回滚成功后-扩展点
             triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
             throw ex;
          }
          catch (TransactionException ex) {
             // can only be caused by doCommit
             if (isRollbackOnCommitFailure()) {
                //异常回滚
                doRollbackOnCommitException(status, ex);
             }
             else {
                //当前事务状态未知--扩展点
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
             }
             throw ex;
          }
          catch (RuntimeException | Error ex) {
             if (!beforeCompletionInvoked) {
                triggerBeforeCompletion(status);
             }
             //异常回滚
             doRollbackOnCommitException(status, ex);
             throw ex;
          }
    
          // Trigger afterCommit callbacks, with an exception thrown there
          // propagated to callers but the transaction still considered as committed.
          try {
             //事务提交成功后-扩展点
             triggerAfterCommit(status);
          }
          finally {
             //事务提交成功后-扩展机制
             triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
          }
    
       }
       finally {
          //完成后清除事务信息,清除当前ThreadLocal中的信息,释放connection,恢复挂起的事务
          cleanupAfterCompletion(status);
       }
    }
    
    /**
     * This implementation of rollback handles participating in existing
     * transactions. Delegates to {@code doRollback} and
     * {@code doSetRollbackOnly}.
     * @see #doRollback
     * @see #doSetRollbackOnly
     */
    @Override
    public final void rollback(TransactionStatus status) throws TransactionException {
       if (status.isCompleted()) {
          throw new IllegalTransactionStateException(
                "Transaction is already completed - do not call commit or rollback more than once per transaction");
       }
    
       DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
       processRollback(defStatus, false);
    }
    
    /**
     * Process an actual rollback.
     * The completed flag has already been checked.
     * @param status object representing the transaction
     * @throws TransactionException in case of rollback failure
     */
    private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
       try {
          boolean unexpectedRollback = unexpected;
    
          try {
    
             //扩展点
             triggerBeforeCompletion(status);
    
             //判读是否存在事务保存点
             if (status.hasSavepoint()) {
                if (status.isDebug()) {
                   logger.debug("Rolling back transaction to savepoint");
                }
                //事务回滚---回滚至事务保存点
                status.rollbackToHeldSavepoint();
             }
             else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                   logger.debug("Initiating transaction rollback");
                }
                //进行事务回滚
                doRollback(status);
             }
             else {
                // Participating in larger transaction
                // 存在事务-但不是新事物(加入的事务)
                if (status.hasTransaction()) {
                   if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                      if (status.isDebug()) {
                         logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                      }
                      //设置事务回滚
                      doSetRollbackOnly(status);
                   }
                   else {
                      if (status.isDebug()) {
                         logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                      }
                   }
                }
                else {
                   logger.debug("Should roll back transaction but cannot - no transaction available");
                }
                // Unexpected rollback only matters here if we're asked to fail early
                if (!isFailEarlyOnGlobalRollbackOnly()) {
                   unexpectedRollback = false;
                }
             }
          }
          catch (RuntimeException | Error ex) {
             triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
             throw ex;
          }
    
          triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
    
          // Raise UnexpectedRollbackException if we had a global rollback-only marker
          if (unexpectedRollback) {
             throw new UnexpectedRollbackException(
                   "Transaction rolled back because it has been marked as rollback-only");
          }
       }
       finally {
          cleanupAfterCompletion(status);
       }
    }
    
    • 用户显示调用提交将事务进行事务回滚 在事务执行过程中,由于某种原因,事务中的代码显式地请求事务回滚的操作,可以直接调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();将当前线程中的事务进行回滚。
  • spring事务传播机制

  • spring事务传播机制共有7种以及对象的特性

    • spring默认的事务传播机制,TransactionDefinition.PROPAGATION_REQUIRED = 0; 如果当前存在事务则加入该事务,如果当前没有事务,则创建一个新的事务

    • TransactionDefinition.PROPAGATION_SUPPORTS = 1; 如果当前存在事务则加入该事务 如果当前没有事务 则以非事务的方式继续运行

    • TransactionDefinition.PROPAGATION_MANDATORY = 2;如果当前存在事务则加入该事务 如果当前没有事务 则抛出异常;

    • TransactionDefinition.PROPAGATION_REQUIRES_NEW = 3; 创建一个新的事务 如果当前存在事务 则把当前事务挂起;

    • TransactionDefinition.PROPAGATION_NOT_SUPPORTED = 4; 以非事务方式运行 如果当前存在事务 则把当前事务挂起

    • TransactionDefinition.PROPAGATION_NEVER = 5;以非事务方式运行如果当前存在事务则抛出异常;

    • TransactionDefinition.PROPAGATION_NESTED = 6;如果当前存在事务则创建一个事务作为当前事务的嵌套事务来运行,如果不存在则创建一个新的事务;

      • 嵌套事务,对于JDBC来说,嵌套事务是通过事务保存点来实现的;当子事务提交,只会释放对应的保存点;子事务回滚,只会回滚至保存点;而父事务能控制所有子事务的提交与回滚的特性;
  • spring事务原理

    • 事务执行流程

      • spring事务是通过PlatformTransactionManager事务管理器来实现的;
      • 当@EnableTransactionManagement开启声明式事务时,spring进行扫描的时候会向容器中注入三个Bean分别是BeanFactoryTransactionAttrubuteSourceAdvisor,TransactionInterceptor, AnnotationTransactionAttributeSource;当spring执行bean的生命周期初始化回调的后置方法postProcessAfterInitialization方法时,会扫描当前类上或者方法中添加@Transactional注解;来创建代理对象,并构建对应的拦截器链;
      • 当调用代理对象的增强方法时,会执行对应的拦截器链上的通知,会执行TransactionInterceptor.invoke方法,完成事务增强;
    • spring事务-DataSourceTransactionManager事务管理原理

      • 获取方法上或类上的事务信息TransactionAttribute,并构建获取TransactionStatus事务状态信息。
      • 通过TransactionSynchronizationManager获取当前线程中ConnectionHolder无事务,则为空;创建新事务时startTransaction,会创建ConnectionHolder并与当前线程做绑定;如果以非事务执行时,就不会创建ConnectionHolder对象,进行事务管理;如果需要挂起当前事务时,解除线程绑定的ConnectionHolder,以及重置TransactionSynchronizationManager事务同步管理器中,当前线程的事务属性信息;如果是嵌套事务则,调用JDBC的底层接口,创建事务保存点即可;对于加入该事务时,执行共有同一个ConnectionHolder对象,并设置相应的事务属性即可;
  • spring声明式事务失效的场景

    • 方法权限问题导致@Transactional失效-声明式事务是基于spring aop来实现的

      • 方法必须是public,非final,不能调用this.方法(即方法必须被代理增强,可以通过获取当前bean的代理增强对象,调用对应的方法即可),未被spring管理
    • 多线程调用

      • DataSourceTransactionManager事务管理是基于Connection连接来实现的,而数据源以及对应的连接是与线程绑定的;(ConnectionHolder是TransactionSynchronizationManager里ThreadLocal中)
    • 数据库不支持事务

    • spring事务回滚失效的几个场景

      • 当前事务回滚的异常不支持或者手动吃了(以及嵌套事务未手动处理子事务的异常)
  • spring事务中,重要的几个组件

    • TransactionStatus用于保存当前事物状态,比如是否只能回滚、是否包含回滚点、是否只读,其实现类内部包含事物操作对象transaction事物操作对象transaction包含不同的实现,比如JDBC的DataSourceTransactionObject、Hibernate的HibernateTransactionObject等
    • BeanFactoryTransactionAttrubuteSourceAdvisor
    • TransactionInterceptor
    • AnnotationTransactionAttributeSource
    • DataSourceTransactionManager
    • TransactionSynchronizationManager
    • TransactionStatus(DefaultTransactionStatus)
    • ConnectionHolder
    • DataSourceUtils :主要用于从当前事务上下文中获取绑定的JDBC连接,并支持Spring的事务管理,并于数据访问技术框架集成;