之前了解到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)

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

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

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

可以看到这里是用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)

可以看到这里会轮询我们创建动态代理类时,注入到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)

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

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



网友评论