范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

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

  前言
  在我们开发过程中,会经常碰到这么一些需求,比如在在主流程执行前,要做一些前置事件,在主流程执行之后,做一些收尾工作。对一些新手程序员,他可能会直接写类似如下的代码  public void execute(){         doBefore();         doBiz();         doAfter();     }  复制代码
  对有一定工作经验的程序员,他可能会用AOP或者用一些设计模式比如模板模式。那我们今天来聊聊下使用spring + spi + aop + 责任链来实现上面的需求代码实现过程分析
  假设主流程只需做一次前置处理和一次后置处理,则伪代码如下  public void execute(){         doBefore();         doBiz();         doAfter();     }  复制代码
  此时我们可以用模板模式或者AOP,这边我们采用AOP。其伪代码如下public class CorMethodInterceptor implements MethodInterceptor {      @Override     public Object invoke(MethodInvocation invocation) throws Throwable {                 try {             doBefore();             Object result = invocation.proceed();             return result;         } catch (Throwable throwable) {            log.error("{}",e);         } finally {             doAfter();         }          return null     } } 复制代码
  如果对这种写法不适应,可以采用@Aspect + @Around方式,效果一个样。
  当主流程需要多次前置处理和多次后置处理时,我们的代码可能就变成public class CorMethodInterceptor implements MethodInterceptor {      @Override     public Object invoke(MethodInvocation invocation) throws Throwable {                 try {             doBefore();             doBefore();             doBefore();             ....             Object result = invocation.proceed();             return result;         } catch (Throwable throwable) {            log.error("{}",e);         } finally {             doAfter();             doAfter();             doAfter();             ...         }          return null     } } 复制代码
  此时这些前置处理或者后置处理看起来就像是一条链,于是我们就可以考虑采用一些设计模式比如责任链或者采用管道模式。本示例我们使用责任链模式代码实现
  1、创建处理器接口public interface AbstarctHandler extends Ordered {      /**      * 预处理回调,实现服务的预处理      * @return true表示流程继续,false表示流程中断,不会继续调用其他处理器或者服务      */     default boolean preHandler(Invocation invocation){         return true;     }      /**      * 整个请求处理完毕回调方法。类似try-catch-finally中的finally。多个afterCompletion按倒叙输出      */     default void afterCompletion(Invocation invocation){}   } 复制代码
  2、创建处理器链public class MethodInterceptorChain {      private final List abstarctHandlers = new ArrayList<>();       public void addHandler(AbstarctHandler handler){         abstarctHandlers.add(handler);     }      public List getHanlders(){         if(CollectionUtils.isEmpty(abstarctHandlers)){             return Collections.emptyList();         }         AnnotationAwareOrderComparator.sort(abstarctHandlers);         return Collections.unmodifiableList(abstarctHandlers);     }  } 复制代码
  3、业务逻辑和责任链整合@Data @AllArgsConstructor @NoArgsConstructor public class CorHandlerInterceptor {      private MethodInterceptorChain chain;       public Object invoke(Invocation invocation) throws Exception {         List abstarctHandlers = chain.getHanlders();         if(CollectionUtils.isEmpty(abstarctHandlers)){             invocation.invoke();         }          boolean isCanExec = true;         int canExecCount = 0;         for (AbstarctHandler abstarctHandler : abstarctHandlers) {               canExecCount++;              if(!abstarctHandler.preHandler(invocation)){                  isCanExec = false;                  break;              }                    }             try{                if(isCanExec){                    return invocation.invoke();                }            }catch (Exception e){                throw new Exception(e);            }finally {                for (int i = 0; i < canExecCount; i++) {                    int j = canExecCount - i - 1;                    abstarctHandlers.get(j).afterCompletion(invocation);                }            }          return null;     }    } 复制代码
  4、创建AOP切面public class CorMethodInterceptor implements MethodInterceptor {      private CorHandlerInterceptor corHandlerInterceptor;      public CorMethodInterceptor(CorHandlerInterceptor corHandlerInterceptor) {         this.corHandlerInterceptor = corHandlerInterceptor;     }      @Override     public Object invoke(MethodInvocation invocation) throws Throwable {         Invocation invoker = Invocation.builder()                 .args(invocation.getArguments())                 .method(invocation.getMethod())                 .target(invocation.getThis()).build();          return corHandlerInterceptor.invoke(invoker);     } } 复制代码
  5、配置切点    @Bean     @ConditionalOnMissingBean     public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor(PointcutProperites pointcutProperites, CorHandlerInterceptor corHandlerInterceptor){         AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor = new AspectJExpressionPointcutAdvisor();         aspectJExpressionPointcutAdvisor.setExpression(pointcutProperites.getExpression());         aspectJExpressionPointcutAdvisor.setAdvice(new CorMethodInterceptor(corHandlerInterceptor));         return aspectJExpressionPointcutAdvisor;     } 复制代码
  6、处理器注入spring  @Bean     @ConditionalOnMissingBean     public CorHandlerInterceptor corHandlerInterceptor(ObjectProvider provider){         MethodInterceptorChain methodInterceptorChain = new MethodInterceptorChain();         loadedHandlerBySpring(provider, methodInterceptorChain);         loadedHanlderBySpi(methodInterceptorChain);         CorHandlerInterceptor corHandlerInterceptor = new CorHandlerInterceptor();         corHandlerInterceptor.setChain(methodInterceptorChain);         return corHandlerInterceptor;     }      @Bean     @ConditionalOnMissingBean     public DefaultHandler defaultHandler(){         return new DefaultHandler();     }      private void loadedHanlderBySpi(MethodInterceptorChain methodInterceptorChain) {         ServiceLoader serviceLoader = ServiceLoader.load(AbstarctHandler.class);         Iterator iterator = serviceLoader.iterator();         while(iterator.hasNext()){             AbstarctHandler abstarctHandler = iterator.next();             log.info("load hander by spi -> 【{}】",abstarctHandler.getClass().getName());             methodInterceptorChain.addHandler(abstarctHandler);         }     }       private void loadedHandlerBySpring(ObjectProvider provider, MethodInterceptorChain methodInterceptorChain) {         List getListBySpring = provider.getIfAvailable();         if(!CollectionUtils.isEmpty(getListBySpring)){             for (AbstarctHandler abstarctHandler : getListBySpring) {                 log.info("load hander by spring -> 【{}】",abstarctHandler.getClass().getName());                 methodInterceptorChain.addHandler(abstarctHandler);             }         }     } 复制代码示例演示
  1、编写业务服务public interface HelloService {      String sayHello(String username); }  复制代码@Service public class HelloServiceImpl implements HelloService {     @Override     public String sayHello(String username) {         return "hello : " + username;     } }  复制代码
  2、编写处理器
  一种通过@Component@Component public class HelloServiceNameInterceptor implements AbstarctHandler {      @Override     public boolean preHandler(Invocation invocation) {         Object[] args = invocation.getArgs();         System.out.println("名称校验-->preHandler");         for (Object arg : args) {             if("张三".equals(arg)){                 return false;             }         }         return true;     }      @Override     public void afterCompletion(Invocation invocation) {         System.out.println("名称校验-->afterCompletion:" + Arrays.toString(invocation.getArgs()));     }      @Override     public int getOrder() {         return 102;     } }  复制代码
  一种通过SPIpublic class HelloServiceSpiInterceptor implements AbstarctHandler {      @Override     public boolean preHandler(Invocation invocation) {         Object[] args = invocation.getArgs();         System.out.println("参数转换-->preHandler");         for (int i = 0; i < args.length; i++) {             if("lisi".equals(args[i])){                 args[i] = "李四";             }         }         return true;     }      @Override     public void afterCompletion(Invocation invocation) {         System.out.println("参数转换-->afterCompletion:" + Arrays.toString(invocation.getArgs()));     }      @Override     public int getOrder() {         return -1;     } }  复制代码
  配置SPI
  内容如下com.github.lybgeek.cor.test.interceptor.HelloServiceSpiInterceptor 复制代码
  3、配置切点表达式lybgeek:   pointcut:     expression: execution(* com.github.lybgeek.cor.test.service..*.*(..)) 复制代码
  4、测试
  观察控制台
  发现处理器正常工作总结
  所谓的可扩展,指在新增功能时,不需要或者少修改原有的功能。用设计原则来讲就是对修改关闭,对扩展开放。本文的示例如果心细的朋友就会发现,这跟springmvc的拦截器实现是很像的
  作者:linyb极客之路
  链接:https://juejin.cn/post/7080330791423016990

2021最新版RabbitMQ面试题总结,每道题都很经典大家对RabbitMQ原理都应该有所了解,下面我们就来看一下关于RabbitMQ原理的面试题。1为什么要引入MQ系统,直接读写数据库不行吗?其实就是问问你消息队列都有哪些使用场景,百亿混战,蔚来抱得美人归?碳纤维迎新主,蔚来李斌笑纳!2022年新年第一天,廊坊万泰复合材料有限责任公司易主,廊坊市飞泽复合材料科技有限公司作为康得复合材料有限责任公司破产重整的战略投资人,正式浮出水面,成2021年使用最多的是哪些收音机?国外玩家最喜欢用哪个收音机?不知道为什么,每当年终岁尾时我都愿回顾一下自己把玩收音机的历程,想想我使用最多的是哪些收音机?这个问题的答案经常令人大吃一惊。一可瑞恩品牌的CCRadio3收音机2021年,我想可开封5G网络建设情况暨全光宽带城市建设情况5G是第五代移动通信技术,在传输速率和资源利用率等方面较4G移动通信提高一个量级或更高,具有增强容量带宽海量终端连接超高可靠低时延的特性。目前,开封移动已开通700M5G基站507司马南,网络新村新风尚先是21年7月,国家网信办就滴滴泄露国家敏感数据,维护国家安全,保障国家利益进行调查,从而下架滴滴。其后,就是司马南手撕联想,怒怼联想。期间,又杀出黑马张捷教授究根究源,刨根溯底,至少翻倍,预期差极大,中鼎股份,还未被深挖的新能源细分龙头中国制造天下无敌,如果再加上欧美先进技术,威力会有多大呢?中西结合疗效好我们都知道中国制造天下无敌,可现实中,中国在很多尖端技术领域,相比欧美日韩等发达国家,依然有比较大的差距,那好停车长续航的快充代步车,空间实用便宜又好养,实拍宝骏KiWiEV宝骏KiWiEV越来越多的消费者开始选择,新能源代步车作为出行方式,特别是在城市里,每天上下班也就几十里或十几里的路程,也不需要太大的车子,小巧的代步就可满足出行需求,并且不限行不美团众包再次调整骑手接单规则,是再次下调配送费的预兆吗?近日美团众包针对骑手接单规则再做调整,新规则对骑手的接单和配送有了更严格的制约!1。当日拒单5单及以上2。当日超时3单及以上3。当日有责取消2单及以上4。客户投诉1单及以上5。一周Java动态代理实现原理以及ASM技术1。ProxyProxyprovidesstaticmethodsforcreatingdynamicproxyclassesandinstances,anditisalsotheJavaScript原型链prototypeproto详解1背景Javascript的继承模型原型链等等概念比较晦涩难懂,很多人过去在使用Javascript的时候并没有刻意去搞明白其中的原理,今天笔者一步一步分析一下JavaScript小米平板5pro使用体验一句话总结看片打游戏且不太在乎与其他设备的联动的直接入(虽然miui13就有了,不过体验如何不清楚),想用来做点文档ppt之类的轻办公也是没有问题的,我用下来感觉良好,5和5pro
德国SAUTER钢琴X孔祥东音乐和阅读的力量深夜,需要安慰的不仅仅是饥饿的胃口,还有每一个灵魂。而我们相信音乐和书籍对于高尚的灵魂来说,一定是最好的慰籍。2020年6月25日晚1900,恰逢端午小长假,在夏日傍晚夜幕降临之时国际顶尖调音大师JimEbdon信赖的奥世声以高端麦克风著称的AustrianAudio(奥世声专业音频)得到了国际顶尖的音乐工程师JimEbdon的首肯及推崇!JimEbdon是业界的调音大神,他曾是魔力红乐队(Maroo每日看点特斯拉发布新家用充电桩等7条快讯1特斯拉发布新家用充电桩,可为其他品牌汽车充电11月3日,特斯拉发布了全新的家用壁挂式电动汽车充电桩,与前代产品不同的是,新的设备并非只能给特斯拉电动汽车充电,全新的J1772第二历史上的今天奥地利作曲家约翰施特劳斯诞生施特劳斯这个名字对古典乐迷来说是如雷贯耳,即使非古典乐迷,也一定听过蓝色多瑙河,也一定曾在拉德斯基圆舞曲响起的时候情不自禁拍起手。1804年的今天(3月14日)是约翰施特劳斯的生日礼赞夏季开启火热音乐之旅快来答题赢好礼SAUTERwithYOU炙热的七八月在钢琴上弹奏音乐便是我爱上夏天的理由如果能够许我一个福利那我一定要拥有这台钢琴自2021年7月1日起你的机会来了!!!点击上图查看详情2021德国SAUTER助力新加坡国际钢琴比赛暨孙麒麟钢琴独奏音乐会2021年4月21日,由全球国际音乐家协会主办苏州金宝玥乐器文化承办的2022新加坡国际钢琴比赛苏州赛区启动仪式暨孙麒麟钢琴独奏音乐会在苏州苏琳音乐厅隆重举行。近百位嘉宾朋友盛装出高端产品从此大众化米家互联网热泵干衣机评测近年来,干衣机以快速烘干效果稳定不受天气影响的优势迅速的进入寻常百姓家,特别是高房价的当下,阳台空间越来越珍贵,干衣机极大的解放了阳台空间,从此阳台可以打造成一个享受生活的区域,这终于解决了静态人体识别问题Aqara高精度人体传感器人体传感器是智能家居中应用最广泛的组件,用于判断是否有人体的活动。传统人体传感器最大的问题在于如果用户长期保持一个固定的姿势,那么人体传感器就无法感受到人的存在。这就造成了当人在客全宅智能之科技感利器Aqara智能墙壁面板S1评测智能墙壁面板出现的时间并不长,但是一出场就获得了不错的市场反响,究其原因,在于智能墙壁面板让智能化看得见摸得着。传统的墙壁开关在升级为智能墙壁面板之后,不论是观感还是交互,都带来强是时候体验真正的全自动了Aqara智能推拉锁D100目前,智能门锁已经是智能家居方面最为成熟的产品之一。不论是从产品的多样性普及率还是从价格看,智能锁已经完全融入了寻常百姓家。目前市面上智能门锁产品众多,很多产品价格已经下探到不足千色彩十足优秀,细节感动人心RedmiMAX86寸电视评测只要能放得下,电视真的是越大越好。即使客厅不大,电视也要尽量选大的,大的电视会带来更棒的沉浸感和体验,这几乎已经成为了共识。对于液晶电视来讲,尺寸是一个劣势相对动不动投影100寸甚