基于Spring实现策略模式
背景:
看多很多策略模式,总结下来实现原理大体都差不多,在这里主要是讲解下自己基于Spring更优雅的实现方案;这个方案主要是看了一些开源rpc和Spring相关源码后的一些思路,所以在此进行总结首先看下比较常见的策略模式写法一个接口或者抽象类,里面两个方法(一个方法匹配类型,一个可替换的逻辑实现方法)不同策略的差异化实现(就是说,不同策略的实现类)使用策略模式1。3。1一个接口,两个方法publicinterfaceIFileStrategy{属于哪种文件解析类型FileTypeResolveEnumgainFileType();封装的公用算法(具体的解析方法)voidresolve(Objectobjectparam);}
1。3。2不同策略的差异化实现
A类型策略具体实现ComponentpublicclassAFileResolveimplementsIFileStrategy{OverridepublicFileTypeResolveEnumgainFileType(){returnFileTypeResolveEnum。FileARESOLVE;}Overridepublicvoidresolve(Objectobjectparam){logger。info(A类型解析文件,参数:{},objectparam);A类型解析具体逻辑}}
B类型策略具体实现ComponentpublicclassBFileResolveimplementsIFileStrategy{OverridepublicFileTypeResolveEnumgainFileType(){returnFileTypeResolveEnum。FileBRESOLVE;}Overridepublicvoidresolve(Objectobjectparam){logger。info(B类型解析文件,参数:{},objectparam);B类型解析具体逻辑}}
默认类型策略具体实现ComponentpublicclassDefaultFileResolveimplementsIFileStrategy{OverridepublicFileTypeResolveEnumgainFileType(){returnFileTypeResolveEnum。FileDEFAULTRESOLVE;}Overridepublicvoidresolve(Objectobjectparam){logger。info(默认类型解析文件,参数:{},objectparam);默认类型解析具体逻辑}}
1。3。3使用策略模式
如何使用呢?我们借助spring的生命周期,使用ApplicationContextAware接口,把对用的策略,初始化到map里面。然后对外提供resolveFile方法即可。ComponentpublicclassStrategyUseServiceimplementsApplicationContextAware{privateMapFileTypeResolveEnum,IFileStrategyiFileStrategyMapnewConcurrentHashMap();publicvoidresolveFile(FileTypeResolveEnumfileTypeResolveEnum,ObjectobjectParam){IFileStrategyiFileStrategyiFileStrategyMap。get(fileTypeResolveEnum);if(iFileStrategy!null){iFileStrategy。resolve(objectParam);}}把不同策略放到mapOverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{MapString,IFileStrategytmepMapapplicationContext。getBeansOfType(IFileStrategy。class);tmepMap。values()。forEach(strategyServiceiFileStrategyMap。put(strategyService。gainFileType(),strategyService));}}
基于Spring服务策略实现
稍微了解过Spring源码都知道,在Spring里面我们定义好的bean被Autowired修饰后,实际这个bean是被Spring进行了统一管理,当需要调用的时候实际是从Spring工厂里拿到这个bean;所以大致思路就是在如何拿到bean之前注入一个代理类,让代理类根据元数据的一些自定义规则后去组装成一个能从Spring里拿到实际的bean元素;基于以上的思路进行编码如下
注解定义自定义一个RouteBizService注解(作用可以理解为Autowired)Target({ElementType。CONSTRUCTOR,ElementType。METHOD,ElementType。PARAMETER,ElementType。FIELD,ElementType。ANNOTATIONTYPE})Retention(RetentionPolicy。RUNTIME)publicinterfaceRouteBizService{StringserviceName();}
自定义一个RouteBizParam参数注解,用于给代理类组装实际beanNameTarget(ElementType。PARAMETER)Retention(RetentionPolicy。RUNTIME)publicinterfaceRouteBizParam{}
定义一个代理类:RouteServiceProxypackagecom。gitee。adapter。proxy;importorg。springframework。context。ApplicationContext;importjava。lang。annotation。Annotation;importjava。lang。reflect。InvocationHandler;importjava。lang。reflect。Method;publicclassRouteServiceProxyTimplementsInvocationHandler{privateStringserviceName;privateApplicationContextcontext;publicRouteServiceProxy(StringserviceName,ApplicationContextcontext){this。serviceNameserviceName;this。contextcontext;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object〔〕args)throwsThrowable{StringrouteCodenull;Annotation〔参数个数索引〕〔注解个数索引〕paramsAnnomethod。getParameterAnnotations();if(paramsAnno!null){for(inti0;iparamsAnno。length;i){if(paramsAnno〔i〕。length0){routeCode(String)args〔i〕;获取到路由的参数值break;}}}returnmethod。invoke(context。getBean(genBeanName(routeCode,serviceName)),args);}paramsellerCode用于区分是哪个Service编码paraminterfaceSimpleName服务接口returnprivateStringgenBeanName(StringsellerCode,StringinterfaceSimpleName){returnnewStringBuilder(sellerCode。toLowerCase())。append(interfaceSimpleName)。toString();}}
ViewCode
基于BeanFactoryPostProcessor定义一个用于扫描RouteBizService修饰的实现类,该类的作用是为了注入代理类packagecom。gitee。adapter。spring;importcom。gitee。adapter。annation。RouteBizService;importcom。gitee。adapter。proxy。RouteServiceProxy;importorg。springframework。beans。BeansException;importorg。springframework。beans。factory。config。BeanDefinition;importorg。springframework。beans。factory。config。BeanFactoryPostProcessor;importorg。springframework。beans。factory。config。ConfigurableListableBeanFactory;importorg。springframework。context。ApplicationContext;importorg。springframework。context。ApplicationContextAware;importorg。springframework。core。annotation。AnnotationUtils;importorg。springframework。util。ClassUtils;importorg。springframework。util。ReflectionUtils;importjava。lang。reflect。Proxy;ClassnameBizRouteServiceProcessorDescriptionbean后置处理器获取所有bean判断bean字段是否被{linkcom。gitee。adapter。annation。RouteBizService}注解修饰publicclassBizRouteServiceProcessorimplementsBeanFactoryPostProcessor,ApplicationContextAware{privateApplicationContextapplicationContext;OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{for(StringbeanDefinitionName:beanFactory。getBeanDefinitionNames()){BeanDefinitionbeanDefinitionbeanFactory。getBeanDefinition(beanDefinitionName);StringbeanClassNamebeanDefinition。getBeanClassName();if(beanClassName!null){Classlt;?clazzClassUtils。resolveClassName(beanClassName,this。getClass()。getClassLoader());ReflectionUtils。doWithFields(clazz,field{RouteBizServicerouteBizServiceAnnotationUtils。getAnnotation(field,RouteBizService。class);if(routeBizService!null){ObjectbeanapplicationContext。getBean(clazz);field。setAccessible(true);修改为代理对象ReflectionUtils。setField(field,bean,Proxy。newProxyInstance(field。getType()。getClassLoader(),newClass〔〕{field。getType()},newRouteServiceProxy(routeBizService。serviceName(),this。applicationContext)));}});}}}OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{this。applicationContextapplicationContext;}}
ViewCode
测试
环境搭建操作系统:Windows集成开发工具:IntelliJIDEA2021项目技术栈:SpringBoot2。2。11JDK1。8项目依赖管理工具:Maven4。0。0
小伙伴们有兴趣想了解内容和更多相关学习资料的请点赞收藏评论转发关注我,后面会有很多干货。
我有一些面试题、架构、设计类资料可以说是程序员面试必备!所有资料都整理到网盘了,需要的话欢迎下载!私信我回复【07】即可免费获取
原文出处:www。shaoqun。coma1437729。html
人民币不具备趋势贬值基础专家全球投资者持续看好A股市场本报记者吴晓璐见习记者韩昱10月11日,中国人民银行(以下简称央行)官方微信号发布央行货币政策司文章《深入推进汇率市场化改革》指出,2022年以来,人民币汇率在合理……
如何预防春季面部皮肤过敏?对抗过敏季1、温水洗脸,及时补水。肌肤在敏感状态下,无论热水还是冷水,都会产生不良的刺激,因此最好用温水洗脸。早春时可使用一些纯保湿的植物性的喷雾,经常给面部补水,肌肤健康后就……
最新报道湖人管理层指责詹姆斯和戴维斯交易拉塞尔威斯布鲁克2021年的夏天,勒布朗詹姆斯和安东尼戴维斯推动湖人队收购了拉塞尔威斯布鲁克,他在洛杉矶的赛季是一场灾难。也许是勒布朗戴维斯推动湖人队收购威斯布鲁克,但管理球星的愿望是总……
天才井喷!中国羽毛球喜迎久违的大捷,包揽全部五个单项的冠亚军北京时间9月19日,2022年斯洛文尼亚青年羽毛球国际挑战赛圆满落幕,派出世青赛班底参赛的中国队大获全胜,包揽了全部5个单项的冠亚军,展现了极其强势的人才储备厚度。男单方……
美芯片大雪崩,暴跌90,外媒我们正在被中国市场淘汰了曾经狂妄自大的美国芯片,这次真的慌了。《经济学人》报道,目前全球半导体市场正在进入一场前所未有的寒冬。过去几个月里,AMD、英特尔、英伟达等美芯企总市值消失1。5亿万亿美……
霜降,霜落秋凉,天寒语暖(致我最牵挂的人)年年秋色最深处,岁岁霜降日日寒,又是一年霜降时。从今日开始,秋已渐远,新冬将至,回首过往,时间在变,人也在变,失去的,别执着;离开的,别挽留。人生就是如此,有人分道……
LekChi的婚纱设计灵感来自希腊神话中众神的美丽玄眉成为了LekChi的缪斯女神,穿着蕾丝和丝绸的婚纱,这灵感来自童话中希腊女神的沼泽。设计师LekChi为2023年春夏设计的最新系列灵感来自希腊神话中众神的美丽,名为……
2022年卫浴洁具十大品牌排行榜1、TOTO亚洲品牌评测指数97。3所属公司:东陶(中国)有限公司始创于1917年日本,智能卫浴全球性品牌,日本历史悠久的卫浴厂家,旗下坐便器、水龙头、浴缸、……
快手电商折叠图片来源视觉中国文财经故事荟,作者何惜金,编辑万天南你好老铁,我是特斯拉。2019年10月18日,特斯拉高调宣布正式入驻快手,这是当时快手开屏广告的醒目标语。……
那些惊艳岁月的句子玲珑骰子安红豆,入骨相思知不知玲珑骰子安红豆,入骨相思知不知。云一涡,玉一梭,淡淡衫儿薄薄罗,轻颦双黛螺。风华是一指流砂,苍老是一段年华。图片源于网络侵删愿余生有人……
海南人请客不爱茅台,只爱这5款平价酒,你喝过几款海南作为我国国际旅游岛,每年接待游客上千万人次,伴随着海南岛旅游业的蓬勃发展,海南当地的餐饮业发展也十分旺盛。糟粕醋火锅、椰子鸡、美味海鲜海南的美食多种多样,简直就是全国各地,……
夜雨丨蒲苇十月十月蒲苇丹桂飘香的良辰,五千年的华夏文明引领着世人的目光,无数敬仰一齐朝向鲜艳的五星红旗迎风招展在亲爱祖国的笑脸上木槿花绚烂的十月,每一片花……