Milo源码解析(四)

拦截事务方法

Milo框架在执行完初始化工作之后,开始等待事务请求,并且拦截该方法,拦截的方法前面已经提到过就是带注解@MiloTCC的方法。这其中拦截方法主要是通过spring的AOP方面的内容。回到我们的项目源码中来,在milo-core模块中,可以找到拦截器AbstractMiloTransactionAspect这个抽象类
在这里插入图片描述
在这里插入图片描述
可以看到拦截的切入点正是@MiloTCC注解,拦截之后交给MiloTransactionAspectHandler处理,MiloTransactionAspectHandler是一个接口方法类,它的实现类在milo-springcloud模块
在这里插入图片描述
SpringCloudMiloTransactionAspect继承了AbstractMiloTransactionAspect并实现了Ordered接口,返回Ordered.HIGHEST_PRECEDENCE,让该拦截器拥有最高优先级,并且在构造方法中注入真正的拦截处理器SpringCloudMiloTransactionAspectHandler,这也是拦截器拦截方法之后的入口
在这里插入图片描述
当我们调用之前测试样例cloud-order的下单接口之后,在执行PaymentService的payment()方法之前会进入到该方法,首先打印一下当前的线程名称,随后从MiloTransactionContextThreadLocal获取事务上下文MiloTransactionContext,MiloTransactionContext是一个单例对象,包含两个ThreadLocal类型静态变量CONTEXT_THREAD_LOCAL、BEAN_THREAD_LOCAL和对应的设置、查询、删除方法,作用是让MiloTransactionContext和MiloTransactionBean与当前线程绑定。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里面用到了两个枚举类MiloRoleEnum和MiloPhaseEnum在这里插入图片描述
MiloRoleEnum前面已经做过说明,MiloPhaseEnum定义了四个枚举值,分别代表了Milo控制整个TCC事务的四个阶段。回到刚才SpringCloudMiloTransactionAspectHandler,此时从MiloTransactionContextThreadLocal拿到的MiloTransactionContext是空的,那么就走到了else逻辑,通过RequestContextHolder和RpcMediator去获取键为MILO_TRANSACTION_CONTEXT的Header参数,结果MiloTransactionContext会依然获取不到,显然这段代码并不是为现在而准备的,最后调用MiloTransactionAspectService的invoke方法。
在这里插入图片描述
MiloTransactionAspectService的invoke方法首先根据事务上下文从MiloTransactionFactoryService获取到事务处理器类型,并通过SpringBeanUtils从容器中获取到对应的事务处理器MiloTransactionHandler,并调用其handle方法。
在这里插入图片描述
MiloTransactionFactoryServiceImpl会根据事务上下文返回对应的事务处理器,Milo总共定义了三个事务处理器的实现类ConsumerMiloTransactionHandler、InitatorMiloTransactionHandler和ProviderMiloTransactionHandler。
在这里插入图片描述
因为此时事务上下文为空,所以返回了InitiatorMiloTransactionHandler.class,我们进入到InitiatorMiloTransactionHandler的handle方法中
在这里插入图片描述
在这里插入图片描述
调用tryPhase方法,调用miloTransactionExecutor.createAndSaveTransaction()去创建事务日志(MiloTransactionExecutor封装了对事务日志的数据库操作),并且事务日志的状态为phase为READY,role为INITIATOR
在这里插入图片描述
在这里插入图片描述
并且获取拦截方法的MiloTCC注解上定义的confirmMethod和cancelMethod对应的值,构造两个MiloInvocationBean分别称为confirmInvocationBean和cancelInvocationBean,MiloInvocationBean封装了四个属性:目标类,方法、参数类型和参数值
在这里插入图片描述
同时用confirmInvocationBean和cancelInvocationBean去构造MiloParticipantBean事务参与者Bean。
在这里插入图片描述
回到刚才的tryPhase方法,创建完事务日志MiloTransactionBean之后,紧接着就创建事务上线文MiloTransactionContext,保存到MiloTransactionContextThreadLocal,接着执行pjp.proceed(),这时代码将进入到PaymentServiceImpl的payment()方法中,执行远程rpc调用扣减库存和扣减账户余额的操作。
在这里插入图片描述
执行完之后payment方法之后将刚才创建的事务日志的记录phase修改为TRYING,如果一切顺利,那么证明TRYING已经完成,回到刚才的InitiatorMiloTransactionHandler,tryPhase调用完成之后线程本地获取事务日志,并执行confirmPhase,否则在tryPhase方法或者confirmPhase方法执行出错后执行cancelPhase,并从线程本地中删除事务日志和事务上下文。
在这里插入图片描述

我的公众号

Alt

发布了122 篇原创文章 · 获赞 127 · 访问量 93万+

猜你喜欢

转载自blog.csdn.net/u010739551/article/details/102662811
今日推荐