在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

系統完成熱部署,并切換該接口的實現

Android編程精選 ? 來源:zhangzhiqiang_0912 ? 作者:Android編程精選 ? 2022-07-23 11:03 ? 次閱讀

近期開發系統過程中遇到的一個需求,系統給定一個接口,用戶可以自定義開發該接口的實現,并將實現打成jar包,上傳到系統中。系統完成熱部署,并切換該接口的實現。

定義簡單的接口

這里以一個簡單的計算器功能為例,接口定義比較簡單,直接上代碼。

publicinterfaceCalculator{
intcalculate(inta,intb);
intadd(inta,intb);
}

該接口的一個簡單的實現

考慮到用戶實現接口的兩種方式,使用spring上下文管理的方式,或者不依賴spring管理的方式,這里稱它們為注解方式和反射方式。calculate方法對應注解方式,add方法對應反射方式。計算器接口實現類的代碼如下:

@Service
publicclassCalculatorImplimplementsCalculator{
@Autowired
CalculatorCorecalculatorCore;
/**
*注解方式
*/
@Override
publicintcalculate(inta,intb){
intc=calculatorCore.add(a,b);
returnc;
}
/**
*反射方式
*/
@Override
publicintadd(inta,intb){
returnnewCalculatorCore().add(a,b);
}
}

這里注入CalculatorCore的目的是為了驗證在注解模式下,系統可以完整的構造出bean的依賴體系,并注冊到當前spring容器中。CalculatorCore的代碼如下:

@Service
publicclassCalculatorCore{
publicintadd(inta,intb){
returna+b;
}
}

反射方式熱部署

用戶把jar包上傳到系統的指定目錄下,這里定義上傳jar文件路徑為jarAddress,jar的Url路徑為jarPath。

privatestaticStringjarAddress="E:/zzq/IDEA_WS/CalculatorTest/lib/Calculator.jar";
privatestaticStringjarPath="file:/"+jarAddress;

并且可以要求用戶填寫jar包中接口實現類的完整類名。接下來系統要把上傳的jar包加載到當前線程的類加載器中,然后通過完整類名,加載得到該實現的Class對象。然后反射調用即可,完整代碼:

/**
*熱加載Calculator接口的實現反射方式
*/
publicstaticvoidhotDeployWithReflect()throwsException{
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
Classclazz=urlClassLoader.loadClass("com.nci.cetc15.calculator.impl.CalculatorImpl");
Calculatorcalculator=(Calculator)clazz.newInstance();
intresult=calculator.add(1,2);
System.out.println(result);
}

注解方式熱部署

如果用戶上傳的jar包含了spring的上下文,那么就需要掃描jar包里的所有需要注入spring容器的bean,注冊到當前系統的spring容器中。其實,這就是一個類的熱加載+動態注冊的過程。

直接上代碼:

/**
*加入jar包后動態注冊bean到spring容器,包括bean的依賴
*/
publicstaticvoidhotDeployWithSpring()throwsException{
SetclassNameSet=DeployUtils.readJarFile(jarAddress);
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
for(StringclassName:classNameSet){
Classclazz=urlClassLoader.loadClass(className);
if(DeployUtils.isSpringBeanClass(clazz)){
BeanDefinitionBuilderbeanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(clazz);
defaultListableBeanFactory.registerBeanDefinition(DeployUtils.transformName(className),beanDefinitionBuilder.getBeanDefinition());
}
}
}

在這個過程中,將jar加載到當前線程類加載器的過程和之前反射方式是一樣的。然后掃描jar包下所有的類文件,獲取到完整類名,并使用當前線程類加載器加載出該類名對應的class對象。判斷該class對象是否帶有spring的注解,如果包含,則將該對象注冊到系統的spring容器中。

DeployUtils包含讀取jar包所有類文件的方法、判斷class對象是否包含sping注解的方法、獲取注冊對象對象名的方法。代碼如下:

/**
*讀取jar包中所有類文件
*/
publicstaticSetreadJarFile(StringjarAddress)throwsIOException{
SetclassNameSet=newHashSet<>();
JarFilejarFile=newJarFile(jarAddress);
Enumerationentries=jarFile.entries();//遍歷整個jar文件
while(entries.hasMoreElements()){
JarEntryjarEntry=entries.nextElement();
Stringname=jarEntry.getName();
if(name.endsWith(".class")){
StringclassName=name.replace(".class","").replaceAll("/",".");
classNameSet.add(className);
}
}
returnclassNameSet;
}
/**
*方法描述判斷class對象是否帶有spring的注解
*/
publicstaticbooleanisSpringBeanClass(Classcla){
if(cla==null){
returnfalse;
}
//是否是接口
if(cla.isInterface()){
returnfalse;
}
//是否是抽象類
if(Modifier.isAbstract(cla.getModifiers())){
returnfalse;
}
if(cla.getAnnotation(Component.class)!=null){
returntrue;
}
if(cla.getAnnotation(Repository.class)!=null){
returntrue;
}
if(cla.getAnnotation(Service.class)!=null){
returntrue;
}
returnfalse;
}
/**
*類名首字母小寫作為spring容器beanMap的key
*/
publicstaticStringtransformName(StringclassName){
Stringtmpstr=className.substring(className.lastIndexOf(".")+1);
returntmpstr.substring(0,1).toLowerCase()+tmpstr.substring(1);
}

刪除jar時,需要同時刪除spring容器中注冊的bean

在jar包切換或刪除時,需要將之前注冊到spring容器的bean刪除。spring容器的bean的刪除操作和注冊操作是相逆的過程,這里要注意使用同一個spring上下文。

代碼如下:

/**
*刪除jar包時需要在spring容器刪除注入
*/
publicstaticvoiddelete()throwsException{
SetclassNameSet=DeployUtils.readJarFile(jarAddress);
URLClassLoaderurlClassLoader=newURLClassLoader(newURL[]{newURL(jarPath)},Thread.currentThread().getContextClassLoader());
for(StringclassName:classNameSet){
Classclazz=urlClassLoader.loadClass(className);
if(DeployUtils.isSpringBeanClass(clazz)){
defaultListableBeanFactory.removeBeanDefinition(DeployUtils.transformName(className));
}
}
}

測試

測試類手動模擬用戶上傳jar的功能。測試函數寫了個死循環,一開始沒有找到jar會拋出異常,捕獲該異常并睡眠10秒。這時候可以把jar手動放到指定的目錄下。

代碼如下:

ApplicationContextapplicationContext=newClassPathXmlApplicationContext("applicationContext.xml");
DefaultListableBeanFactorydefaultListableBeanFactory=(DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
while(true){
try{
hotDeployWithReflect();
//hotDeployWithSpring();
//delete();
}catch(Exceptione){
e.printStackTrace();
Thread.sleep(1000*10);
}
}

-End-

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8598

    瀏覽量

    151157
  • 代碼
    +關注

    關注

    30

    文章

    4788

    瀏覽量

    68612

原文標題:動態上傳jar包熱部署實戰

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    功率器件設計基礎(十)——功率半導體器件的結構函數

    樣品活動進行中,掃碼了解詳情/前言/功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 12-23 17:31 ?156次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(十)——功率半導體器件的結構函數

    功率器件設計基礎(九)——功率半導體模塊的熱擴散

    樣品活動進行中,掃碼了解詳情/前言/功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 12-16 17:22 ?537次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(九)——功率半導體模塊的熱擴散

    功率器件設計基礎(八)——利用瞬態阻計算二極管浪涌電流

    /前言/功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 12-11 01:03 ?115次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(八)——利用瞬態<b class='flag-5'>熱</b>阻計算二極管浪涌電流

    功率器件設計基礎(七)——等效模型

    /前言/功率半導體熱設計是實現IGBT、SiCMOSFET高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 12-03 01:03 ?789次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(七)——<b class='flag-5'>熱</b>等效模型

    功率器件設計基礎(六)——瞬態測量

    功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低系統
    的頭像 發表于 11-26 01:02 ?821次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(六)——瞬態<b class='flag-5'>熱</b>測量

    功率器件設計基礎(五)——功率半導體熱容

    /前言/功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 11-19 01:01 ?256次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(五)——功率半導體熱容

    混合部署 | 在迅為RK3568上同時部署RT-Thread和Linux系統

    和安全性的同時,靈活處理復雜的任務場景。 混合部署 在一般情況下,iTOP-RK3568 的四個 Cortex-A55 核心通常運行 Linux 系統,這種架構稱為對稱多處理(SMP)。而 AMP
    發表于 11-01 10:31

    功率器件的設計基礎(二)——阻的串聯和并聯

    /前言/功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低
    的頭像 發表于 10-29 08:02 ?317次閱讀
    功率器件的<b class='flag-5'>熱</b>設計基礎(二)——<b class='flag-5'>熱</b>阻的串聯和并聯

    功率器件設計基礎(一)——功率半導體的

    功率半導體熱設計是實現IGBT、碳化硅SiC高功率密度的基礎,只有掌握功率半導體的設計基礎知識,才能完成精確設計,提高功率器件的利用率,降低系統
    的頭像 發表于 10-22 08:01 ?1117次閱讀
    功率器件<b class='flag-5'>熱</b>設計基礎(一)——功率半導體的<b class='flag-5'>熱</b>阻

    kvm切換器怎么實現鍵盤熱鍵切換

    器的工作原理 KVM切換器的核心功能是將一組鍵盤、鼠標和顯示器與多臺計算機連接,通過某種方式實現對這些計算機的控制。KVM切換器的工作原理可以分為以下幾個步驟: 1.1 輸入設備連接
    的頭像 發表于 10-17 09:36 ?859次閱讀

    混合部署 | 在迅為RK3568上同時部署RT-Thread和Linux系統

    和安全性的同時,靈活處理復雜的任務場景。 混合部署 在一般情況下,iTOP-RK3568 的四個 Cortex-A55 核心通常運行 Linux系統,這種架構稱為對稱多處理(SMP)。而 AMP
    發表于 09-18 10:54

    三行代碼完成生成式AI部署

    LLM加載與推理部署能力,實現了OpenVINO對CNN網絡、生成式模型、LLM網絡主流模型的全面推理支持。
    的頭像 發表于 08-30 16:49 ?421次閱讀
    三行代碼<b class='flag-5'>完成</b>生成式AI<b class='flag-5'>部署</b>

    PLC冗余系統的相互切換機制

    在工業自動化控制系統中,PLC(可編程邏輯控制器)的冗余設計是確保系統高可靠性和穩定性的重要手段。PLC冗余系統通過配置兩個或多個功能相同的PLC控制器,實現主備用的自動
    的頭像 發表于 06-19 10:42 ?1802次閱讀

    鴻蒙實戰開發-本地部署、SmartPerf 編譯部署指導文檔

    apt-get install nodejs npm []() centos 系統中使用yum安裝,先切換到root用戶下,命令如下: sudo su sudo yum -y install
    發表于 05-09 14:23

    蒙牛集團部署EAM設備管理系統 完成數據互聯實現資產全生命周期管理

    ”。該系統將打通集團內 SAP、MES、WMS 和數采等平臺,完成數據互聯,實現集團資產全生命周期管理。 作為工業自動化、信息化和數字化轉型領域的全球領先企業之一,羅克韋爾自動化參與了蒙牛集團EAM
    的頭像 發表于 04-07 10:13 ?591次閱讀
    主站蜘蛛池模板: 欧美性黑人十极品hd| 一级精品视频| 天天操天天操天天射| 男人女人真曰批视频播放| 亚洲 欧美 日韩 在线 中文字幕| 免费人成动漫在线播放r18| 午夜一区二区在线观看| 一区二区三区视频在线| 色吧综合| 天天色天天草| 日本免费一区二区在线观看| 欧美一级看片免费观看视频在线| 天天躁天天狠天天透| 亚洲一级视频在线观看| 日本免费网站| 人人干国产| 永久黄网站色视频免费观看| 国产一级特黄全黄毛片| 操人网站| 色欧美色图| 天天操天天干天天做| 乱j伦小说在线阅读| 久草婷婷| 999国产精品| 屁屁影院在线| 最新色视频| 国产美女作爱| h视频国产| 两性色午夜视频自由成熟的性| 免费观看欧美一级高清| 亚洲国产精品第一区二区| www.av片| 男啪女r18肉车文| 国产日韩三级| 中文字幕一区二区三区在线播放 | 日韩性插| 日本免费看黄| 精品国产理论在线观看不卡| 特级黄一级播放| 天天操天天干天天拍| 亚洲免费色|