美文网首页
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事务完全解析

    事务是什么?了解事务的原理吗?说下Spring的事务原理,能自己实现Spring事务原理吗?先自我检测下这些知识掌...

  • Spring事物原理完全解析

    事务是什么?了解事务的原理吗?说下Spring的事务原理,能自己实现Spring事务原理吗?先自我检测下这些知识掌...

  • 程序员之Spring

    1. Spring事务 spring的事务实现原理Spring事务将connection放入到当前线程的threa...

  • spring事务的实现原理

    spring实现事务的原理 Spring事务 的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring...

  • Spring事务传播机制

    1.Spring事务执行的原理; Spring事务使用AOP的机制实现,会在@Transcactional注解修饰...

  • 面试问题记录(一) Day50 2019-01-09

    并发中的常用锁,乐观锁和悲观锁,实现及使用 事务的特性,原理,spring如何实现事务 spring的实现机制,I...

  • Spring声明事务原理及核心源码分析

    上一篇 << >> Spring声明事务底层实现原理 Spring事务是基于AOP环绕通知和异常通知实现的Spri...

  • Spring事务(一)

    Spring事务的实现原理: Spring事务底层是基于数据库事务和AOP机制的 ⾸先对于使⽤了@Transact...

  • Spring嵌套事务原理

    Spring 采用保存点(Savepoint)实现嵌套事务原理Spring采用一个物理事务,但是结合着savepo...

  • Spring事物失效原因整理

    Spring事物实现方式及原理 Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spri...

网友评论

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

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