聊一聊责任链模式

网站建设5年前发布
45 0 0

责任链模式(Chain of Responsibility Pattern)是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止,属于行为型模式。下面放一张足球比赛的图,通过层层传递,最终射门。通过这张图,可以更好的理解责任链模式。,20230306135316826bddd095d4e23c1fa7144a60ccfdbf578383401,2023030613513863f19c73696f8af412f8796b36edc78cd005d3666,抽象接口RequestHandler,抽象类BaseRequestHandler,具体处理类AHandler,当然还有具体的处理类B、C等等,这里不展开赘述。, 使用类Client,202303061353175161cbd023f8e0f8b133984b3bb4c2d4499ba0972,场景一,前两年,在一家金融公司待过一段时间,其中就有一个业务场景:一笔订单进来,会先在后台通过初审人员进行审批,初审不通过,订单流程结束。初审通过以后,会转给终审人员进行审批,不通过,流程结束;通过,流转到下个业务场景。对于这块业务代码,之前一代目是一个叫知了的同事,他撸起袖子就是干,一套if-else干到底。后来,技术老大CodeReview,点名要求改掉这块。于是乎,想到用用设计模式吧,然后就噼里啪啦一顿改。(当然,比较复杂的情况,还是可以用工作流来处理这个场景,当时碍于时间成本,也就放弃了)。,场景二,上家公司对接甲方爸爸的时候,对方会调用我们接口,将数据同步过来。同样,我们需要将处理好的数据,传给他们。由于双方传输数据都是加密传输,所以在接受他们数据之前,需要对数据进行解密,验签,参数校验等操作。同样,我们给他们传数据也需要进行加签,加密操作。,具体案例,话不多说,对于场景二,我来放一些伪代码,跟大家一起探讨下。1、一切从注解开始,我这里自定义了一个注解@Duty​,这个注解有spring的@Component注解,也就是标记了这个自定义注解的类,都是交给spring的bean容器去管理。注解中,有两个属性:1.type,定义相同的type类型的bean,会被放到一个责任链集合中。2.order,同一个责任链集合中,bean的排序,数值越小,会放到链路最先的位置,优先处理。,2、定义一个顶层的抽象接口IHandler,传入2个泛型参数,供后续自定义。,3、定义一个责任链bean的管理类HandleChainManager,用来存放不同业务下的责任链路集合。在该类中,有一个Map和两个方法。,handleMap:这个map会存放责任链路中,具体的执行类,key是注解@Duty​中定义的type值,value是标记了@Duty注解的bean集合,也就是具体的执行类集合。,setHandleMap:传入具体执行bean的集合,存放在map中。,executeHandle:从map中找到具体的执行bean集合,并依次执行。,4、定义一个配置类PatternConfiguration​,用于装配上面的责任链管理器HandleChainManager。,5、具体的处理类:SignChainHandler、EncryptionChainHandler、RequestChainHandler​,这里我以SignChainHandler​为例。在具体处理类上标记自定义注解@Duty​,该类会被注入到bean容器中,实现IHandler接口,只需关心自己的handle方法,处理具体的业务逻辑。,6、具体怎么调用?这里我写了个测试controller直接调用,具体如下:,7、执行结果,会按照注解中标记的order依次执行。 ,20230306135140d5184d009cf8aec96246626ceeceac0a027462306,至此,完工。又可以开心的撸代码了,然后在具体的执行类中,又是一顿if-else。。。,Mybatis中的缓存接口Cache,cache作为一个缓存接口,最主要的功能就是添加和获取缓存的功能,作为接口它有11个实现类,分别实现不同的功能,下面是接口源码和实现类。,20230306135318196f4a8917d497c206d4313f3b4885bf04413e485,下面,我们来看下其中一个子类LoggingCache的源码。主要看他的putObject方法和getObject方法,它在方法中直接传给下一个实现去执行。这个实现类其实是为了在获取缓存的时候打印缓存的命中率的。,最后,经过Cache​接口各种实现类的处理,最终会到达PerpetualCache这个实现类。与之前的处理类不同的是,这个类中有一个map,在map中做存取,也就是说,最终缓存还是会保存在map中的。,4.2.1DispatcherServlet类,DispatcherServlet 核心方法 doDispatch。HandlerExecutionChain只是维护HandlerInterceptor的集合,可以向其中注册相应的拦截器,本身不直接处理请求,将请求分配给责任链上注册处理器执行,降低职责链本身与处理逻辑之间的耦合程度。,4.2.2HandlerExecutionChain类,这里分析的几个方法,都是从DispatcherServlet类的doDispatch方法中请求的。,在applyPreHandle方法中,执行triggerAfterCompletion方法,获取拦截器,执行applyPostHandle方法,责任链太长或者处理时间过长,会影响整体性能。,如果节点对象存在循环引用时,会造成死循环,导致系统崩溃。,​编程文档: https://gitee.com/cicadasmile/butte-java-note,应用仓库: https://gitee.com/cicadasmile/butte-flyer-parent,

© 版权声明

相关文章