纠纷奇闻社交美文家庭
投稿投诉
家庭城市
爱好生活
创业男女
能力餐饮
美文职业
心理周易
母婴奇趣
两性技能
社交传统
新闻范文
工作个人
思考社会
作文职场
家居中考
兴趣安全
解密魅力
奇闻笑话
写作笔记
阅读企业
饮食时事
纠纷案例
初中历史
说说童话
乐趣治疗

聊聊如何让你的业务代码具有可扩展性

3月23日 凉夕夏投稿
  前言
  在我们开发过程中,会经常碰到这么一些需求,比如在在主流程执行前,要做一些前置事件,在主流程执行之后,做一些收尾工作。对一些新手程序员,他可能会直接写类似如下的代码publicvoidexecute(){doBefore();doBiz();doAfter();}复制代码
  对有一定工作经验的程序员,他可能会用AOP或者用一些设计模式比如模板模式。那我们今天来聊聊下使用springspiaop责任链来实现上面的需求代码实现过程分析
  假设主流程只需做一次前置处理和一次后置处理,则伪代码如下publicvoidexecute(){doBefore();doBiz();doAfter();}复制代码
  此时我们可以用模板模式或者AOP,这边我们采用AOP。其伪代码如下publicclassCorMethodInterceptorimplementsMethodInterceptor{OverridepublicObjectinvoke(MethodInvocationinvocation)throwsThrowable{try{doBefore();Objectresultinvocation。proceed();}catch(Throwablethrowable){log。error({},e);}finally{doAfter();}returnnull}}复制代码
  如果对这种写法不适应,可以采用AspectAround方式,效果一个样。
  当主流程需要多次前置处理和多次后置处理时,我们的代码可能就变成publicclassCorMethodInterceptorimplementsMethodInterceptor{OverridepublicObjectinvoke(MethodInvocationinvocation)throwsThrowable{try{doBefore();doBefore();doBefore();。。。。Objectresultinvocation。proceed();}catch(Throwablethrowable){log。error({},e);}finally{doAfter();doAfter();doAfter();。。。}returnnull}}复制代码
  此时这些前置处理或者后置处理看起来就像是一条链,于是我们就可以考虑采用一些设计模式比如责任链或者采用管道模式。本示例我们使用责任链模式代码实现
  1、创建处理器接口publicinterfaceAbstarctHandlerextendsOrdered{预处理回调,实现服务的预处理returntrue表示流程继续,false表示流程中断,不会继续调用其他处理器或者服务defaultbooleanpreHandler(Invocationinvocation){}整个请求处理完毕回调方法。类似trycatchfinally中的finally。多个afterCompletion按倒叙输出defaultvoidafterCompletion(Invocationinvocation){}}复制代码
  2、创建处理器链publicclassMethodInterceptorChain{privatefinalListabstarctHandlersnewArrayList();publicvoidaddHandler(AbstarctHandlerhandler){abstarctHandlers。add(handler);}publicListgetHanlders(){if(CollectionUtils。isEmpty(abstarctHandlers)){returnCollections。emptyList();}AnnotationAwareOrderComparator。sort(abstarctHandlers);returnCollections。unmodifiableList(abstarctHandlers);}}复制代码
  3、业务逻辑和责任链整合DataAllArgsConstructorNoArgsConstructorpublicclassCorHandlerInterceptor{privateMethodInterceptorCpublicObjectinvoke(Invocationinvocation)throwsException{ListabstarctHandlerschain。getHanlders();if(CollectionUtils。isEmpty(abstarctHandlers)){invocation。invoke();}booleanisCanEintcanExecCount0;for(AbstarctHandlerabstarctHandler:abstarctHandlers){canExecCif(!abstarctHandler。preHandler(invocation)){isCanE}}try{if(isCanExec){returninvocation。invoke();}}catch(Exceptione){thrownewException(e);}finally{for(inti0;icanExecCi){intjcanExecCounti1;abstarctHandlers。get(j)。afterCompletion(invocation);}}}}复制代码
  4、创建AOP切面publicclassCorMethodInterceptorimplementsMethodInterceptor{privateCorHandlerInterceptorcorHandlerIpublicCorMethodInterceptor(CorHandlerInterceptorcorHandlerInterceptor){this。corHandlerInterceptorcorHandlerI}OverridepublicObjectinvoke(MethodInvocationinvocation)throwsThrowable{InvocationinvokerInvocation。builder()。args(invocation。getArguments())。method(invocation。getMethod())。target(invocation。getThis())。build();returncorHandlerInterceptor。invoke(invoker);}}复制代码
  5、配置切点BeanConditionalOnMissingBeanpublicAspectJExpressionPointcutAdvisoraspectJExpressionPointcutAdvisor(PointcutProperitespointcutProperites,CorHandlerInterceptorcorHandlerInterceptor){AspectJExpressionPointcutAdvisoraspectJExpressionPointcutAdvisornewAspectJExpressionPointcutAdvisor();aspectJExpressionPointcutAdvisor。setExpression(pointcutProperites。getExpression());aspectJExpressionPointcutAdvisor。setAdvice(newCorMethodInterceptor(corHandlerInterceptor));returnaspectJExpressionPointcutA}复制代码
  6、处理器注入springBeanConditionalOnMissingBeanpublicCorHandlerInterceptorcorHandlerInterceptor(ObjectProviderListprovider){MethodInterceptorChainmethodInterceptorChainnewMethodInterceptorChain();loadedHandlerBySpring(provider,methodInterceptorChain);loadedHanlderBySpi(methodInterceptorChain);CorHandlerInterceptorcorHandlerInterceptornewCorHandlerInterceptor();corHandlerInterceptor。setChain(methodInterceptorChain);returncorHandlerI}BeanConditionalOnMissingBeanpublicDefaultHandlerdefaultHandler(){returnnewDefaultHandler();}privatevoidloadedHanlderBySpi(MethodInterceptorChainmethodInterceptorChain){ServiceLoaderserviceLoaderServiceLoader。load(AbstarctHandler。class);IteratoriteratorserviceLoader。iterator();while(iterator。hasNext()){AbstarctHandlerabstarctHandleriterator。next();log。info(loadhanderbyspi【{}】,abstarctHandler。getClass()。getName());methodInterceptorChain。addHandler(abstarctHandler);}}privatevoidloadedHandlerBySpring(ObjectProviderListprovider,MethodInterceptorChainmethodInterceptorChain){ListgetListBySpringprovider。getIfAvailable();if(!CollectionUtils。isEmpty(getListBySpring)){for(AbstarctHandlerabstarctHandler:getListBySpring){log。info(loadhanderbyspring【{}】,abstarctHandler。getClass()。getName());methodInterceptorChain。addHandler(abstarctHandler);}}}复制代码示例演示
  1、编写业务服务publicinterfaceHelloService{StringsayHello(Stringusername);}复制代码ServicepublicclassHelloServiceImplimplementsHelloService{OverridepublicStringsayHello(Stringusername){returnhello:}}复制代码
  2、编写处理器
  一种通过ComponentComponentpublicclassHelloServiceNameInterceptorimplementsAbstarctHandler{OverridepublicbooleanpreHandler(Invocationinvocation){Object〔〕argsinvocation。getArgs();System。out。println(名称校验preHandler);for(Objectarg:args){if(张三。equals(arg)){}}}OverridepublicvoidafterCompletion(Invocationinvocation){System。out。println(名称校验afterCompletion:Arrays。toString(invocation。getArgs()));}OverridepublicintgetOrder(){return102;}}复制代码
  一种通过SPIpublicclassHelloServiceSpiInterceptorimplementsAbstarctHandler{OverridepublicbooleanpreHandler(Invocationinvocation){Object〔〕argsinvocation。getArgs();System。out。println(参数转换preHandler);for(inti0;iargs。i){if(lisi。equals(args〔i〕)){args〔i〕李四;}}}OverridepublicvoidafterCompletion(Invocationinvocation){System。out。println(参数转换afterCompletion:Arrays。toString(invocation。getArgs()));}OverridepublicintgetOrder(){return1;}}复制代码
  配置SPI
  内容如下com。github。lybgeek。cor。test。interceptor。HelloServiceSpiInterceptor复制代码
  3、配置切点表达式lybgeek:pointcut:expression:execution(com。github。lybgeek。cor。test。service。。。(。。))复制代码
  4、测试
  观察控制台
  发现处理器正常工作总结
  所谓的可扩展,指在新增功能时,不需要或者少修改原有的功能。用设计原则来讲就是对修改关闭,对扩展开放。本文的示例如果心细的朋友就会发现,这跟springmvc的拦截器实现是很像的
  作者:linyb极客之路
  链接:https:juejin。cnpost7080330791423016990
投诉 评论 转载

永州传连载11湘江源头与萍洲爱情故事湘江源头,藏在深闺人未识张效雄单说湘江源头,怎么也不逊色与上述八景任何一个。每当秋天来临,遍布蓝山县湘江源头湘江大峡谷的近十万株红枫,进入最佳观赏期。连绵四五……单聊游戏中的格斗嗨,你们好。你们应该知道,我是一个游戏主播博主,但我没有录制的部分游戏,诸如动作类的,体育竞技类的也不少。我在大学时期,学的是体育,专项是武术与格斗战术。借着今天的灵感,我想跟……喝酒后拉肚子?与这5个原因有关,希望喜欢喝酒的你早点看到小金是一名销售,平常经常有应酬需要喝酒,几年来一直都相安无事。但在近期,小金发现自己在喝酒后会频繁拉肚子,没有喝酒的时候就好好的,这让他怀疑自己是不是患上了什么病。但不喝……造车新势力格局生变,蔚小理已然掉队?钛媒体焦点在经历了金九银十各种集中促销活动之后,11月也就自然而然地成为了各大车企传统的交付大月。日前,造车新势力品牌也在第一时间陆续公布了各自的11月交付成绩单。哪吒汽车继续以1……拥抱热爱,做长期主义的实践者人生不设限,任何事都不是阻碍你前进的理由,只有你的内在,你的心态,才会阻碍你。如果一个念头在你的脑海里反复出现,你想做,却总是担心、纠结、害怕,以至于这个念头占用了你太多的时间……读念书的孩子有感无意中在网上看到一本书《念书的孩子》,觉得很喜欢,就给孩子买了。当时的想法是晚上睡前可以和孩子一起读会书,给孩子找点事情做,增加亲子时光。昨天书就收到了,饭后孩子就拿出书……择君记和浮图缘各追8集一个追不下去,一个看上瘾2022年的上线的古偶爆款连连,从刘亦菲的《梦华录》到王鹤与虞书欣主演的《苍兰诀》都让国产古偶剧的品质直线上升,而到了2023年,观众对于对古偶剧的期待值更高,不少观众更是将爆……我们是知己,当身心孤寂不复存在,难道就失色了吗?新丽萌口述青春散落色彩,结局苍白幸福,挥不尽的惆怅,肆虐脆弱思绪。我多么想,静静地把一切都遗忘,奈何不知该如何去做到。我多么想,揽一缕清风入怀,独邀明月共举杯,去感受那份……周庆葭推动能源创新融合发展增强能源安全保障能力国家电投集团四川公司党委书记、董事长,国家电投集团西南能源研究院董事长、总经理(院长)周庆葭。国家电投集团西南能源研究院供图中新网成都3月17日电(单鹏)四川‘富水缺煤、……啧啧,小米这个瓜太大了印度政府执法局(ED)在社交平台上宣布:根据1999年外汇管理法规定,扣押了小米在银行账户汇总的555。127亿卢比(约合人民币48亿元)。原因是小米非法向境外机构……聊聊如何让你的业务代码具有可扩展性前言在我们开发过程中,会经常碰到这么一些需求,比如在在主流程执行前,要做一些前置事件,在主流程执行之后,做一些收尾工作。对一些新手程序员,他可能会直接写类似如下的代码pu……打个赌!新疆好不好?166万平方公里告诉你一个答案新疆的美,是166万平方公里的可能都说不来新疆,不知中国之辽阔。在这166万平方公里的土地上,存在了太多的可能,不亲自来一趟你永远不知道新疆到底有多美。今天我带你一……
三体热播,科学家为何自杀?何为纳米技术?C罗的面子都不给,曼联更衣室大乱,媒体揭露球队内部混乱国安要签林良铭?种种因素表明可能性非常大动画丨智慧城市万物互联智能生活触手可及王子文吊带裙,彰显贵气穆里尼奥执教国米二队,老狼王将被送出梅阿查,回罗马关键是年薪中老年男人的眉毛变长,等于长寿?是这样的吗?医生给你解答抓好幼儿园三年黄金期,娃进入小学后不用报补习班,照样是尖子生基本确定!广东国手落选,场均8。9分创四年新低,杜锋无力偏袒酒驾司机肇事逃逸,汽车自动报警叫来警察游天下秋意凉!学生族喜欢的秋季绝美露营地原来是这里封面天天见超实用的西装搭配,优雅显贵又气质,这些高阶穿法赶紧学起来
最留恋的幸福奇才赢下G4让热火成季后赛首轮唯一被横扫,球队会发生巨变吗?教你怎么做各种花样面包在父母鼓励中长大的孩子,长大后为什么反而会变平庸?驮盐的驴子汉景帝的长子刘荣怎么死的刘荣为什么被废15年前的这部电视剧演技派大咖云集,邓超高圆圆只能当配角打酱飞机行李托运可以带化妆品吗潜水脚蹼的作用是什么婴儿眼屎的清理方法这是个奇迹,长胶选手竟然能够夺冠老舍《东方学院留英回忆之三》原文及赏析

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找美丽时装彩妆资讯历史明星乐活安卓数码常识驾车健康苹果问答网络发型电视车载室内电影游戏科学音乐整形