怎么用源碼分析PlayFrameworkhotswap

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)怎么用源碼分析Play Framework hotswap,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

洪山ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!

Play Framework hotswap的賣點(diǎn)就在于 hot swap,正如它自己宣稱的:

reach your maximum productivity。play! 允許開發(fā)人員修改java文件,保存,然后刷新瀏覽器,立馬可以看到效果。不需要編譯,也不需要重啟服務(wù)器

Java 要想實(shí)現(xiàn)動(dòng)態(tài)更新 class 文件,不外乎兩種手段:替換 classloader、替換 JVM。因?yàn)樘鎿Q JVM 引起的開銷更大,需要維護(hù) JVM 的堆、棧等運(yùn)行信息,所以 hot swap 通常是選擇替換 classloader。比如 grails 里面就是選擇替換 classloader,它會(huì)自己維護(hù)一個(gè)線程,定期輪詢?cè)次募欠癜l(fā)生修改,以替換原來的 classloader。那么 play! 宣稱的 hot swap 又是怎么實(shí)現(xiàn)的呢?

讓我們來看看play! 的內(nèi)部流程:

1. play! 使用了 Apache Mina 作為底層的 http server,然后使用了自己關(guān)于 Mina IoHandler 接口的實(shí)現(xiàn)—— HttpHandler

2. 當(dāng)瀏覽器發(fā)起一個(gè) request:

2.1 Mina Server 生成一個(gè) Mina Request,轉(zhuǎn)發(fā)給 HttpHandler 的 messageReceived 方法

2.2 play! 解析 Mina Request 和 Mina Session,包裝成自己的 Request 對(duì)象

Request request = parseRequest(minaRequest, session);

2.3 play! 檢測(cè) Route 文件修改情況,根據(jù) Route 配置信息將 Route/Action 的信息賦給 Request 對(duì)象

Router.detectChanges();  Router.route(request);

2.4 play! 根據(jù)當(dāng)前配置的開發(fā)模式來采用不同的策略調(diào)用 Action 來理 Request

if (Play.mode == Play.Mode.DEV) {  Invoker.invokeInThread(new MinaInvocation(session, minaRequest, minaResponse, request, response));  } else {  Invoker.invoke(new MinaInvocation(session, minaRequest, minaResponse, request, response));  }

2.5 如果 play! 當(dāng)前是 DEV 模式,invokeInThread方法會(huì)讓 invocation 對(duì)象代理 run() 方法

public void run() {  try {  before();  execute();  after();  } catch (Throwable e) {  onException(e);  } finally {  _finally();  }  }

咱們來看看 before() 方法:

public static void before() {  Thread.currentThread().setContextClassLoader(Play.classloader);  if(!Play.id.equals("test")) {  Play.detectChanges();  if (!Play.started) {  Play.start();  }  }  //  }

在 Play 類的 detectChanges() 方法里面,有這么一句:

classloader.detectChanges();

哈哈,play! 修改源文件后,刷新瀏覽器即見效的奧秘就在這里了。再進(jìn)去看看 play! 自定義 classloader 的 detectChanges() 方法:

public void detectChanges() {  // Now check for file modification  List<ApplicationClass> modifieds = new ArrayList<ApplicationClass>();  for (ApplicationClass applicationClass : Play.classes.all()) {  if (applicationClass.timestamp < applicationClass.javaFile.lastModified()) {  applicationClass.refresh();  modifieds.add(applicationClass);  }  }  List<ClassDefinition> newDefinitions = new ArrayList<ClassDefinition>();  Map<Class, Integer> annotationsHashes = new HashMap<Class, Integer>();  for (ApplicationClass applicationClass : modifieds) {  annotationsHashes.put(applicationClass.javaClass, computeAnnotationsHash(applicationClass.javaClass));  if (applicationClass.compile() == null) {  Play.classes.classes.remove(applicationClass.name);  } else {  applicationClass.enhance();  BytecodeCache.cacheBytecode(applicationClass.enhancedByteCode, applicationClass.name, applicationClass.javaSource);  newDefinitions.add(new ClassDefinition(applicationClass.javaClass, applicationClass.enhancedByteCode));  }  }  try {  HotswapAgent.reload(newDefinitions.toArray(new ClassDefinition[newDefinitions.size()]));  } catch (ClassNotFoundException e) {  throw new UnexpectedException(e);  } catch (UnmodifiableClassException e) {  throw new UnexpectedException(e);  }  // Check new annotations  for (Class clazz : annotationsHashes.keySet()) {  if (annotationsHashes.get(clazz) != computeAnnotationsHash(clazz)) {  throw new RuntimeException("Annotations change !");  }  }  // Now check if there is new classes or removed classes  int hash = computePathHash();  if (hash != this.pathHash) {  // Remove class for deleted files !!  for (ApplicationClass applicationClass : Play.classes.all()) {  if (!applicationClass.javaFile.exists()) {  Play.classes.classes.remove(applicationClass.name);  }  if(applicationClass.name.contains("$")) {  Play.classes.classes.remove(applicationClass.name);  }  }  throw new RuntimeException("Path has changed");  }  }

HotswapAgent類的 reload 方法如下:

public static void reload(ClassDefinition definitions) throws UnmodifiableClassException, ClassNotFoundException {  instrumentation.redefineClasses(definitions);  }

讀到這里,也就弄清楚了 play! 怎么實(shí)現(xiàn) hot swap 的原理了,還是調(diào)用java.lang.instrument目錄下的類和方法來實(shí)現(xiàn)的 hot swap。不存在魔法,play! 還是選擇了替換 classloader,只不過這個(gè)替換動(dòng)作發(fā)生在處理 http request 的時(shí)候,于是開發(fā)人員用起來就是“刷新瀏覽器就可以看見效果了”。

上述就是小編為大家分享的怎么用源碼分析Play Framework hotswap了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享題目:怎么用源碼分析PlayFrameworkhotswap
標(biāo)題URL:http://muchs.cn/article6/ipjiog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、電子商務(wù)域名注冊(cè)、網(wǎng)站收錄商城網(wǎng)站、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)