美文网首页
spring事务的实现原理

spring事务的实现原理

作者: kele2018 | 来源:发表于2022-08-05 17:17 被阅读0次

    之前了解到spring的事务是通过AOP实现的,但具体怎么实现的并不十分清楚,今天梳理了下,现在记录下其中涉及到的API的关联关系,方便以后查阅。
    1、开发中实现事务的时候,会在controller中注入service,然后在service相应的方法上添加@Transactional注解,容器启动的时候,service赋值的时候,会赋一个动态代理类。实际运行的时候,会先执行事务相关的代码,接着执行我们的业务代码,最后再执行事务代码。

    @RestController
    @RequestMapping("/api")
    @Slf4j
    public class MthInsureIdsTweetController {
    
       @Autowired
       MthInsureIdsTweetService mthInsureIdsTweetService;
    
       @PostMapping("/v1/tweet/testTransaction")
       @ApiOperation("事务测试")
       public FastResponse<Object> testTransaction(@RequestBody MthInsureIdsTweetReq mthInsureIdsTweetReq) throws CommonException {
           Object operate = mthInsureIdsTweetService.testTransaction(mthInsureIdsTweetReq);
           return ResponseUtils.success(operate);
       }
    }
    
    @Service
    public class MthInsureIdsTweetServiceImpl extends ServiceImpl<MthInsureIdsTweetMapper, MthInsureIdsTweet> implements MthInsureIdsTweetService {
       @Override
       @Transactional
       public Object testTransaction(MthInsureIdsTweetReq mthInsureIdsTweetReq) {
           return null;
       }
    }
    

    动态代理过程:

    执行栈帧:

    wrapIfNecessary:339, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    postProcessAfterInitialization:291, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    applyBeanPostProcessorsAfterInitialization:455, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    initializeBean:1808, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:620, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
    getObject:-1, 353580491 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$219)
    getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)
    resolveCandidate:276, DependencyDescriptor (org.springframework.beans.factory.config)
    doResolveDependency:1389, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    resolveDependency:1309, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    resolveFieldValue:656, AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement (org.springframework.beans.factory.annotation)
    inject:639, AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement (org.springframework.beans.factory.annotation)
    inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
    postProcessProperties:399, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
    populateBean:1431, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    doCreateBean:619, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
    lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
    getObject:-1, 353580491 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$219)
    getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
    doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
    getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)
    preInstantiateSingletons:953, DefaultListableBeanFactory (org.springframework.beans.factory.support)
    finishBeanFactoryInitialization:918, AbstractApplicationContext (org.springframework.context.support)
    refresh:583, AbstractApplicationContext (org.springframework.context.support)
    refresh:145, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
    refresh:730, SpringApplication (org.springframework.boot)
    refreshContext:412, SpringApplication (org.springframework.boot)
    run:302, SpringApplication (org.springframework.boot)
    run:1301, SpringApplication (org.springframework.boot)
    run:1290, SpringApplication (org.springframework.boot)
    main:30, MthApplication (com.meditrusthealth.insure.ids.admin)
    
    image.png

    可以看到这里有一个获取拦截器的操作,假如能获取到,就创建动态代理对象,反之就返回目标对象;
    执行栈帧:

    findCandidateAdvisors:94, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
    findEligibleAdvisors:96, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    getAdvicesAndAdvisorsForBean:78, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    wrapIfNecessary:339, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
    
    
    image.png

    可以看到这里获取到了两个【Advisor】(先不要关心Advisor是啥),我们现在关注第一个【BeanFactoryTransactionAttributeSourceAdvisor】,看下这个对象接下来到哪里去了;


    image.png

    可以看到在创建动态代理对象的时候,注入到了【ProxyFactory】中,ProxyFactory是用来创建代理对象的工厂,观察它的继承结构,我们可以看到它是一个【AdvisedSupport】;


    image.png
    可以看到这里是用cjlib字节码提升来创建动态代理类的,所以我们需要关注注入到enhancer中的callbacks,因为现在是讨论事务,我们先关注第一个【CglibAopProxy$DynamicAdvisedInterceptor】

    事务执行阶段:

    获取拦截器链

    getInterceptorsAndDynamicInterceptionAdvice:80, DefaultAdvisorChainFactory (org.springframework.aop.framework)
    getInterceptorsAndDynamicInterceptionAdvice:470, AdvisedSupport (org.springframework.aop.framework)
    intercept:678, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)  //  注意这里的拦截器
    testTransaction:-1, MthInsureIdsTweetServiceImpl$$EnhancerBySpringCGLIB$$df377619 (com.meditrusthealth.insure.ids.admin.service.Impl)
    testTransaction:80, MthInsureIdsTweetController (com.meditrusthealth.insure.ids.admin.controller)
    invoke:-1, MthInsureIdsTweetController$$FastClassBySpringCGLIB$$ddc8c683 (com.meditrusthealth.insure.ids.admin.controller)
    invoke:218, MethodProxy (org.springframework.cglib.proxy)
    invokeJoinpoint:783, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:64, AspectJAfterThrowingAdvice (org.springframework.aop.aspectj)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:57, AfterReturningAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:58, MethodBeforeAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    proceed:89, MethodInvocationProceedingJoinPoint (org.springframework.aop.aspectj)
    argsLog:237, WebApiInterceptor (com.meditrusthealth.fast.common.web.interceptor)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:62, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:483, Method (java.lang.reflect)
    invokeAdviceMethodWithGivenArgs:634, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    invokeAdviceMethod:624, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    invoke:72, AspectJAroundAdvice (org.springframework.aop.aspectj)
    proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:97, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
    proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    intercept:698, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
    testTransaction:-1, MthInsureIdsTweetController$$EnhancerBySpringCGLIB$$2d3691b5 (com.meditrusthealth.insure.ids.admin.controller)
    
    image.png

    可以看到这里会轮询我们创建动态代理类时,注入到ProxyFactory中的Advisor,然后使用Advisor中的pointcut进行过滤,最后得到我们的拦截器;那么获取到的拦截器是什么,事务又是在哪里执行的呢?
    执行栈帧:

    invokeWithinTransaction:340, TransactionAspectSupport (org.springframework.transaction.interceptor)
    invoke:119, TransactionInterceptor (org.springframework.transaction.interceptor)
    proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    intercept:698, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
    testTransaction:-1, MthInsureIdsTweetServiceImpl$$EnhancerBySpringCGLIB$$df377619 (com.meditrusthealth.insure.ids.admin.service.Impl)
    testTransaction:80, MthInsureIdsTweetController (com.meditrusthealth.insure.ids.admin.controller)
    invoke:-1, MthInsureIdsTweetController$$FastClassBySpringCGLIB$$ddc8c683 (com.meditrusthealth.insure.ids.admin.controller)
    invoke:218, MethodProxy (org.springframework.cglib.proxy)
    invokeJoinpoint:783, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:64, AspectJAfterThrowingAdvice (org.springframework.aop.aspectj)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:57, AfterReturningAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:58, MethodBeforeAdviceInterceptor (org.springframework.aop.framework.adapter)
    proceed:175, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    proceed:89, MethodInvocationProceedingJoinPoint (org.springframework.aop.aspectj)
    argsLog:237, WebApiInterceptor (com.meditrusthealth.fast.common.web.interceptor)
    invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
    invoke:62, NativeMethodAccessorImpl (sun.reflect)
    invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
    invoke:483, Method (java.lang.reflect)
    invokeAdviceMethodWithGivenArgs:634, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    invokeAdviceMethod:624, AbstractAspectJAdvice (org.springframework.aop.aspectj)
    invoke:72, AspectJAroundAdvice (org.springframework.aop.aspectj)
    proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    invoke:97, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
    proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    proceed:753, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
    intercept:698, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
    testTransaction:-1, MthInsureIdsTweetController$$EnhancerBySpringCGLIB$$2d3691b5 (com.meditrusthealth.insure.ids.admin.controller)
    
    image.png

    到这里可能会有一个疑问BeanFactoryTransactionAttributeSourceAdvisor是什么时候注入容器中的,而TransactionInterceptor是什么时候注入到BeanFactoryTransactionAttributeSourceAdvisor中的,事实上在容器启动的时候,这些事情就做好了;


    image.png

    最后再解释下Advisor,pointCut,Advice?
    Advisor是PointCut和Advice的组合;PointCut主要做筛选工作,Advice是具体动作;


    image.png image.png image.png

    相关文章

      网友评论

          本文标题:spring事务的实现原理

          本文链接:https://www.haomeiwen.com/subject/xdxuwrtx.html