专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Java类隔离应用多Jar包支持

  案例需求
  现在有一个统一管理平台,用于统一对接三方平台,屏蔽相同业务三方平台的差异性,减少内部平台对接的成本。正常情况下三方平台提供的SDK是通用的(和内部平台无关),但是有一些比较特殊的三方(假如是三方平台A),他提供的SDK是给内部平台定制的。
  这时就需要根据访问统一管理平台的内部平台类型,动态的选择使用哪个三方平台A的Jar包,比如内部平台A访问三方平台A,就需要调用为A定制的Jar包。
  这个需求需要解决如下两个问题:如何在同一套环境中同时存在多个同平台不同版本的Jar包(这些Jar包中的类大部分相同,只有预设的配置参数不同)?如何根据内部平台类型,选择需要调用的Jar包?类加载
  我们知道如果想要使用一个类,那么这个类必须通过类加载器将其加载到内存中,在未自定义类加载器之前,JVM是通过ApplicationClassLoader、ExtensionClassLoader、BootstrapClassLoader这三个类加载器基于双亲委派机制完成类的加载。这三个类加载器具有各自加载类的范围如下图所示:
  类隔离机制
  要想解决上面的第一个问题(多个同平台不同版本Jar包同时存在),就必须先了解一下类隔离机制。
  类隔离机制原理其实很简单,就是让每个三方平台A定制的Jar使用单独的类加载器来加载,这样每个Jar包之间相互隔离不会相互影响。这是因为即使同一个类使用不同的类加载器加载,对于JVM也是两个不同的类(虽然类的结构相同),在JVM中类的唯一标识是:类加载器类名。
  要保证不同Jar包内的类隔离,还需要做到一点,就是Jar包中的某个类使用某个类加载器加载,那么其引用的类均使用该类加载器加载,这就是类加载传导规则。
  代码实现
  使用IDEA创建三个Maven项目:thirdpartyAforA:三方平台A为内部平台A定制的JarthirdpartyAforB:三方平台A为内部平台B定制的Jarunifiedmanagementplatform:统一管理平台,用于通过访问的内部平台类型,动态选择调用三方平台A的Jar
  项目:thirdpartyAforA
  pom。xmllt;?xmlversion1。0encodingUTF8?projectxmlnshttp:maven。apache。orgPOM4。0。0xmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:maven。apache。orgPOM4。0。0http:maven。apache。orgxsdmaven4。0。0。xsdmodelVersion4。0。0modelVersiongroupIdcom。thirdparty。AgroupIdthirdpartyAforAartifactIdversion1。0SNAPSHOTversiondescription三方平台A为内部平台A定制Jar包descriptionpropertiesmaven。compiler。source17maven。compiler。sourcemaven。compiler。target17maven。compiler。targetpropertiesdependenciesdependencygroupIdcn。hutoolgroupIdhutoolallartifactIdversion5。8。5versiondependencydependenciesproject
  定义两个类:TPAAccessService:用于提供给调用方的统一调用入口类SendRequestProvider:Jar内部使用的类,用于提供向三方平台A发送请求的类,另外一个作用是验证类加载传导规则
  TPAAccessService。javaTPA(ThirdPartyA:三方平台A简称)该类为调用方提供统一的方法调用入口,调用三方A只需要使用该类即可since20231149:45publicclassTPAAccessService{publicstaticvoidsend(){SendRequestProvider。send();}}
  SendRequestProvider。javaimportcn。hutool。core。lang。Console;该类提供向三方平台A发送请求的方法since20231149:48classSendRequestProvider{三方平台A为内部平台A预设的密钥,用于加解密privatestaticfinalStringSECRETKEYAAAAAAAAAAA;发送请求到三方平台Apublicstaticvoidsend(){Console。log(〔ATPA〕密钥:{}ClassLoader:{},SECRETKEY,SendRequestProvider。class。getClassLoader());}}
  项目:thirdpartyAforB
  与thirdpartyAforA基本相同,除了SendRequestProvider。java中的密钥不同,如下所示:classSendRequestProvider{三方平台A为内部平台B预设的密钥,用于加解密privatestaticfinalStringSECRETKEYBBBBBBBBBBB;发送请求到三方平台Apublicstaticvoidsend(){Console。log(〔BTPA〕密钥:{}ClassLoader:{},SECRETKEY,SendRequestProvider。class。getClassLoader());}}
  项目:
  unifiedmanagementplatform
  pom。xmllt;?xmlversion1。0encodingUTF8?projectxmlnshttp:maven。apache。orgPOM4。0。0xmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:maven。apache。orgPOM4。0。0http:maven。apache。orgxsdmaven4。0。0。xsdmodelVersion4。0。0modelVersiongroupIdcom。umpgroupIdunifiedmanagementplatformartifactIdversion1。0SNAPSHOTversiondescription统一管理平台descriptionpropertiesmaven。compiler。source17maven。compiler。sourcemaven。compiler。target17maven。compiler。targetpropertiesdependenciesdependencygroupIdorg。projectlombokgroupIdlombokartifactIdversion1。18。24versiondependencydependencygroupIdcn。hutoolgroupIdhutoolallartifactIdversion5。8。5versiondependencydependenciesproject
  定义两个类:TPAClassLoader:自定义类加载器,用于加载为内部平台定制的相应Jar中类的类Main:测试内部平台调用效果
  TPAClassLoader。javaimportcn。hutool。core。lang。Console;importlombok。SneakyThrows;importjava。io。File;importjava。io。FileNotFoundException;importjava。net。URL;importjava。net。URLClassLoader;importjava。util。concurrent。ConcurrentHashMap;importjava。util。concurrent。ConcurrentMap;为加载三方平台A提供的Jar自定义的类加载器since202311410:02publicclassTPAClassLoaderextendsURLClassLoader{用于缓存相应平台的类加载器,防止重复创建和加载类,造成内存泄漏privatestaticfinalConcurrentMapString,TPAClassLoaderCLASSLOADERCACHEnewConcurrentHashMap();privateTPAClassLoader(URL〔〕urls,ClassLoaderparent){super(urls,parent);}用于获取相应三方平台Jar包中的类,如果已经加载直接返回,未加载通过TAPClassLoader加载类,完成后返回paraminternalPlatformCode内部平台编码,例如:内部平台A的编码就是AparamtapJarPath为相应内部平台定制的三方平台Jar路径paramclassName待获取类的全限定类名return类的Class对象SneakyThrowspublicstaticClasslt;?getClass(StringinternalPlatformCode,StringtapJarPath,StringclassName){TPAClassLoaderclassLoadergetInstance(internalPlatformCode,tapJarPath);Console。log(获取内部平台{}的类:{},internalPlatformCode,className);returnclassLoader。loadClass(className);}用于获取对应内部平台的类加载器,类加载器相对于内部平台是单例的,保证单例使用单例设计模式DCL的方式paraminternalPlatformCode内部平台编码,例如:内部平台A的编码就是AparamtapJarPath为相应内部平台定制的三方平台Jar路径return内部平台对应的类加载器privatestaticTPAClassLoadergetInstance(StringinternalPlatformCode,StringtapJarPath)throwsException{finalStringkeybuildKey(internalPlatformCode,tapJarPath);TPAClassLoaderclassLoaderCLASSLOADERCACHE。get(key);if(classLoader!null){returnclassLoader;}synchronized(TPAClassLoader。class){classLoaderCLASSLOADERCACHE。get(key);if(classLoader!null){returnclassLoader;}FilejarFilenewFile(tapJarPath);if(!jarFile。exists()){thrownewFileNotFoundException(未找到三方平台AJar包文件:tapJarPath);}classLoadernewTPAClassLoader(newURL〔〕{jarFile。toURI()。toURL()},getSystemClassLoader());Console。log(为内部平台{}创建类加载器:{},internalPlatformCode,classLoader);CLASSLOADERCACHE。put(key,classLoader);returnclassLoader;}}用于生成缓存对应内部平台类加载器的KeyparaminternalPlatformCode内部平台编码,例如:内部平台A的编码就是AparamtapJarPath为相应内部平台定制的三方平台Jar路径return缓存KeyprivatestaticStringbuildKey(StringinternalPlatformCode,StringtapJarPath){returninternalPlatformCode。concat(::)。concat(tapJarPath);}}
  Main。javaimportcn。hutool。core。lang。Console;importcn。hutool。core。util。RandomUtil;importcn。hutool。core。util。ReflectUtil;importlombok。SneakyThrows;importjava。util。HashMap;importjava。util。Map;MainauthorZhaoHaichunsince202311410:34publicclassMain{该Map只是测试使用,用于临时保持三方平台A提供的Jar包路径,实际开发会通过文件上传到服务器,然后获取上传路径,通过路径加载privatestaticfinalMapString,StringTPAJARPATHMAPnewHashMap();privatestaticfinalStringTAPACCESSSERVICENAMEcom。thirdparty。TPAAccessService;static{TPAJARPATHMAP。put(A,C:UserszhaohDesktopTemptapjarthirdpartyAforA1。0SNAPSHOT。jar);TPAJARPATHMAP。put(B,C:UserszhaohDesktopTemptapjarthirdpartyAforB1。0SNAPSHOT。jar);}SneakyThrowspublicstaticvoidmain(String〔〕args){for(inti0;i5;i){用于随机生成待访问的内部平台StringinternalPlatformCodeString。valueOf((char)RandomUtil。randomInt(A,B1));通过访问的内部平台查询三方平台A为其提供的Jar路径StringjarPathTPAJARPATHMAP。get(internalPlatformCode);通过上述信息,使用相应的类加载器加载或直接获取类com。thirdparty。TPAAccessServiceClasslt;?clazzTPAClassLoader。getClass(internalPlatformCode,jarPath,TAPACCESSSERVICENAME);调用其相应的方法ReflectUtil。invokeStatic(clazz。getMethod(send));Console。log();}}}测试步骤
  编写完成上述代码后,按照下面步骤执行:使用Mavenpackage打包项目:thirdpartyAforA、thirdpartyAforB将打包完成的Jar拷贝到测试目录,上面实例代码为:C:UserszhaohDesktopTemptapjar目录下修改Main类静态代码块中的路径与Jar包路径一致执行Main类中的main方法
  输出结果如下:(每次输出可能不同)为内部平台A创建类加载器:com。ump。TPAClassLoader568db2f2获取内部平台A的类:com。thirdparty。TPAAccessService〔ATPA〕密钥:AAAAAAAAAAAClassLoader:com。ump。TPAClassLoader568db2f2获取内部平台A的类:com。thirdparty。TPAAccessService〔ATPA〕密钥:AAAAAAAAAAAClassLoader:com。ump。TPAClassLoader568db2f2为内部平台B创建类加载器:com。ump。TPAClassLoader179d3b25获取内部平台B的类:com。thirdparty。TPAAccessService〔BTPA〕密钥:BBBBBBBBBBBClassLoader:com。ump。TPAClassLoader179d3b25获取内部平台B的类:com。thirdparty。TPAAccessService〔BTPA〕密钥:BBBBBBBBBBBClassLoader:com。ump。TPAClassLoader179d3b25获取内部平台A的类:com。thirdparty。TPAAccessService〔ATPA〕密钥:AAAAAAAAAAAClassLoader:com。ump。TPAClassLoader568db2f2
  通过上面的输出结果可以看出:内部平台A和B分别只创建了一次类加载器创建完成类加载器后,后续均通过缓存中获取相应的类加载器在Jar包中TPAAccessService调用了SendRequestProvider,而SendRequestProvider输出的日志中类加载器同加载TPAAccessService的类加载器相同,说明类加载传导规则内部平台A调用,输出的密钥是AAAAAAAAAAA,B调用输出的密钥是BBBBBBBBBBB,说明为内部平台提供的Jar均加载到内存,而且通过类加载器实现了类的隔离

有多少人像我一样把行程码截屏保存了?你现在敢随便出门吗?陪伴了一千多个日夜的行程码从我们的手机上和生活中消失了,真的让人有点五味杂陈。昨天,我专门截屏保存了,就当留个纪念吧。说实话,我是动态清零政策的支持者。前不久,我还就这个问题写过一泓森一五九糖尿病人这样吃水果,血糖控制更安全,吃得也放心水果富含膳食纤维维生素矿物质果胶果酸水分糖分等物质,水果对于糖尿病人来说,有利有弊,适量吃水果除了能补充水分解渴润燥之外,还能够补充维生素CB族维生素以及矿物质,也能摄入一定量的膳弘一法师这辈子你最爱的人,是上辈子最爱你的人弘一法师曾说这辈子你最爱的人,就是上辈子最爱你的人,来的都是债,要还,还要还得干干净净,离开就是还清了,即使错是别人的,业也是自己的。前世不欠,今生不见,若是相见,定有亏欠。都说人搜狐张朝阳称年轻人大量囤退烧药是自私Tech星球12月15日消息,近日,搜狐创始人董事局主席兼首席执行官张朝阳在其个人账号发布动态称,如果你是年轻人,只买一盒退烧药是一种慈善行为,大量囤退烧药就是一种自私。值得一提的世界杯决赛在即,我看好这支国家队!2022年卡塔尔世界杯已经进入最激动人心的决赛阶段这届世界杯哪名球员你印象最深刻是高效进球的姆巴佩还是阻挡点球的门将利瓦科维奇还是星光熠熠的梅西C罗内马尔相信很多人和小新一样都做过微信出手,这类小程序被彻底封杀前段时间AI绘画大火,相信大家都已经听说了。虽然AI绘画已经强大到让专业绘画人士产生了危机感,但需要说明的是,AI绘画其实并不算特别前沿的技术。所谓的AI绘画,只不过是AIGC(A河南前11个月外贸超7700亿元加工贸易近六成民营企业外贸占比提升顶端新闻河南商报记者金艾琳据郑州海关统计,今年前11个月,河南省外贸进出口总值7709。3亿元,比去年同期(下同)增长8。新能源汽车出口和原油进口皆倍增前11个月,手机及其零部件为Waymo的无人驾驶出租车现在在凤凰城从事机场接送Waymo正派其完全无人驾驶的汽车来处理一些你能想到的最棘手的接客类型机场旅行。该公司宣布,进出凤凰城天港机场的乘客现在可以叫到该公司的乘客专用车辆,这表明Alphabet公司愿意南通农商银行多点发力打好年末收官战来源消费日报2022年以来,疫情静默封城房地产市场调整下行建筑行业风险持续暴露企业投资扩产意愿弱化等因素对南通市经济发展冲击较大,存贷款业务增长呈现疲弱态势。南通农商银行加压奋进,兴证策略走出存量博弈,迎接增量入市引言2022年以来,市场并不缺钱,但市场的极端波动风险偏好的剧烈收缩导致资金面呈现显著的存量博弈。岁末年初,投资者普遍关注明年市场资金面能否好转?增量资金来自何方?因此,本报告系统厦门钨业18亿两大业务同时扩产机构扎堆四基金跻进股东前十长江商报消息长江商报记者沈右荣福建稀土集团旗下的厦门钨业(600549。SH)继续稳步前行。厦门钨业专注于钨钼稀土和能源新材料三大核心业务,12月14日晚间,公司宣告,旗下两大业务
华润啤酒2022年营收上涨净利微跌,未来利润增长要靠跨界白酒和啤酒高端化2023年3月24日,华润啤酒(控股)有限公司(以下简称华润啤酒)发布2022年全年业绩。财报显示,华润啤酒于2022年的综合营业额为人民币352。63亿元,较2021年增长5。6绳彩飞扬凤凰苑幼儿园推进幼小科学衔接荆楚网(湖北日报网)讯(记者林杉通讯员张纯尹琪)跳绳是幼小衔接中学习准备的一项重要任务。3月,武汉经济技术开发区军山凤凰苑幼儿园大班的小朋友开展了绳彩飞扬快乐成长幼小衔接主题活动。历史上广东十虎中到底谁的功夫最高呢?我来回答这个问题,喜欢的话可以关注我所谓的广东十虎是指清朝末年广东的十位武林高手,他们是王隐林黄澄可苏黑虎黄麒英周泰谭济筠黎仁超陈铁志苏灿梁坤。耳熟能详的黄飞鸿并不在十虎之列,他的足协办理戴伟浚手续效率极高,为什么归化卡尔德克就不行?戴维俊是中国人呀,所以简单一可能考虑到卡尔德克的年龄问题二也会考虑归化球员适不适用中国国家队三也会大规模归化对中国国家队的影响。原因很简单因为戴伟浚年轻而且从中国香港到中国内地就是2022年春晚你看了吗?哪个节目让你印象深刻?对不起没看在睡觉。如果让我给2022年春晚小品类节目打分的话,我必须给小品父与子打个高分!此小品无论是编导还是演员,其表现都是杠杠的!小品充满了正能量,洋溢着鲜活的生活气息,体现了哈登会成为中国优质偶像球星吗?我觉得哈登不会成为中国优质偶像球星。哈登的性格还不错,最起码不会随便伤害人,这一点是值得肯定的,但是哈登毕竟是在美国长大的,很多习惯还是受到了美国文化的影响。美国的文化和中国的传统深圳楼市还能回到2022吗?深圳楼市还能回到2020吗?相信这是很多入局者的期盼,因为只有回到2020很多人才能解套,这一波楼市下行套住很多人。那我们就来回顾一下2020年深圳楼市发生什么?2020年初全国疫有千亿市值巨头人均薪酬大降3成!券业降薪真的来了么在降薪传闻一波接一波传出之际,部分证券公司的人均薪酬似乎真得降了。据南都湾财社记者不完全统计,截至目前,信达证券方正证券安信证券招商证券东方财富已公布2022年度财报及薪酬数据。报欲入股国机智骏?滴滴回应不便评价,以公告为准3月28日,赣州市一位知情官员向有关媒体透露,国机智骏正在引入外部投资者滴滴,双方进行了一年多的谈判,目前谈判已进入尾声。同日,滴滴相关人士表示,不便评价,此事涉及到上市公司,以上博鳌亚洲论坛广交会消博会等陆续举行推进高质量发展搭建平台除了即将拉开帷幕的博鳌亚洲论坛,广交会消博会等备受关注的国际展会近期也将陆续举行,为国内外交流合作推进高质量发展搭建平台。第133届广交会首批进境展品通关第133届广交会将于4月1M2即将突破300万亿,专家建议尽快消费应对通胀,你为啥不听话?此时此刻,钱正变得越来越不值钱了。看看2月份的广义货币量M2的情况,余额已经高达275。52万亿元,同比增长12。9,创下5年新高。按照这个速度,今年突破300万亿几乎没有悬念。要
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网