當前位置:首頁 » 操作系統 » extjs源碼分析與開發實例寶典

extjs源碼分析與開發實例寶典

發布時間: 2023-05-30 18:37:22

『壹』 log4j2源碼分析

1.概述
1.1.組件概覽
1.2.靈活的配置
1.2.1.插件發現機制
1.2.2.插件裝配機制
1.2.3.配置文件基本元素與對象的映射關系
2.屬性佔位符
2.1.概述
2.2.Interpolator插值器
2.3.默認屬性配置
3.Logger
3.1.配置示例
3.2.配置詳解
3.3.Logger繼承機制
4.Appender
4.1.概述
4.2.框架支持的Appender實現
4.3.常用Appender詳解
4.3.1.ConsoleAppender
4.3.2.RollingFileAppender
5.Layout
5.1.概述
5.2.PatternLayout
5.2.1.模式字元串
6.Manager
7.Filter

在log4j2中,LogManager就是日誌的門面,相當於slf4j-api中的LoggerFactory.
框架為每個類載入分配了一個單獨的LoggerContext,用於管理所有創建出來的Logger實例.
ContextSelector則負責管理類載入器到對應的LoggerContext實例之間的映射關系.
log4j2中,有5個關鍵概念:

組件架構如下:

在log4j2中,一切皆插件,框架通過 PluginRegistry 掃描並發現插件配置.

PluginRegistry 支持兩種掃描方式

插件配置以 PluginType 的形式保存在插件注冊表中, PluginType 的作用類似於spring中 BeanDefinition ,定義了如何創建插件實例.
插件類通過 @PluginFactory 註解或者 @PluginBuilderFactory 註解配置孝沖插件實例的實例化和屬性注入方式.

log4j2知道如何實例化插件後,我們就可以通過編寫配置文件(如:log4j2.xml),進行插件的實例化和屬性注入了.
Configuration 全局配置對象負責保存所有解析到的配置.
通過 ConfigurationFactory.getConfiguration() 可以使用不同的工廠生產不同的配御或置對象,不同的 Configuration 實現可以解析不同格式的配置,如:xml,yaml,json等.

以xml文件為例,文件中每個元素都會最終對應一個插件實例,元素名稱實際就是PluginType中的name,實例的屬性可以從子元素對應的實例獲取,也可以從自身元素的屬性配置獲取.

因此,xml中dom樹的元素嵌套關系,也就是log4j組件實例的引用嵌套關系.

xml,yaml,json格式文件都可以描述這種嵌套關系,因此log4j2中定義了與文件格式無關的數據結構,Node來抽象配置.

AbstractConfiguration.setup() 負責提取配置,形成Node樹.
AbstractConfiguration.doConfigure() 負責根據Node樹,進行插件實例化和屬性注入.

在log4j2中,環境變數信息(鍵值對)被封裝為StrLookup對象,該對象作用類似於spring框架中的PropertySource.

在配置文件中,基本上所有的值的配置都可以通過參數佔位符引用環境變數信息,格式為:${prefix:key}.

Interpolator內部以Map<String,StrLookup>的方式,封裝了很多StrLookuo對象,key則對應巧拆殲參數佔位符${prefix:key}中的prefix.

同時,Interpolator內部還保存著一個沒有prefix的StrLookup實例,被稱作默認查找器,它的鍵值對數據來自於log4j2.xml配置文件中的<Properties>元素的配置.

當參數佔位符${prefix:key}帶有prefix前綴時,Interpolator會從指定prefix對應的StrLookup實例中進行key查詢,

當參數佔位符${key}沒有prefix時,Interpolator則會從默認查找器中進行查詢.

Interpolator中默認支持的StrLookup查找方式如下(StrLookup查找器實現類均在org.apache.logging.log4j.core.lookup包下):

注意:Properties元素一定要配置在最前面,否則不生效.

log4j2框架會根據LoggerConfig的name建立對象之間的繼承關系.這種繼承機制與java的package很像,name以點進行名稱空間分割,子名稱空間繼承父名稱空間.
名稱空間可以是全限定類名,也可以是報名.整個配置樹的根節點就是RootLogger.
舉例:假如我們的配置的Logger如下:

當通過LogManager.getLogger(name)獲取Logger實例時,會根據name逐級遞歸直到找到匹配的LoggerConfig,或者遞歸到Root根節點為止.

追加器,負責控制Layout進行LogEvent的序列化,以及控制Manager對序列化後的位元組序列進行輸出.

在log4j2.xml配置文件中,配置方式如下:

控制台追加器,用於把日誌輸出到控制台,一般本地調試時使用.
配置示例如下:

文件滾動追加器,用於向本地磁碟文件中追加日誌,同時可以通過觸發策略(TriggeringPolicy)和滾動策略(RolloverStrategy)控制日誌文件的分片,避免日誌文件過大.
線上環境常用.

常用的觸發策略包含兩種:

滾動策略的實現包含兩種:

配置示例如下:

布局對象,職責是把指定的LogEvent轉換成可序列化對象(如:String),或者直接序列化成位元組數組.

log4j2支持很多的序列化格式,如:普通模式字元串,JSON字元串,yaml字元串,XML格式字元串,HTML字元串等等.

類體系如下:

模式布局是我們最常使用的,它通過PatternProcessor模式解析器,對模式字元串進行解析,得到一個List<PatternConverter>轉換器列表和List<FormattingInfo>格式信息列表.

在PatternLayout序列化時,會遍歷每個PatternConverter,從LogEvent中取不同的值進行序列化輸出.

模式字元串由3部分組成,格式為:%(格式信息)(轉換器名稱){選項1}{選項2}...

模式字元串的格式為:
%-(minLength).-(maxLength)(轉換器名稱){選項字元串}
minLength代表欄位的最小長度限制,當欄位內容長度小於最小限制時,會進行空格填充.
minLength前面的-負責控制對齊方式,默認為右對齊(左邊空格填充),如果加上-,則會切換為左對齊方式(右邊空格填充)
maxLength代表欄位的最大長度限制,當欄位內容長度大於最大限制時,會進行內容階段
maxLength前面的-負責控制階段方向,默認為左側階段,如果加上-,則會切換為右側階段
minLength和maxLength之間用點分隔.
格式信息中所有屬性都是可選的,不配置,則使用默認值

log4j2會通過 PluginManager 收集所有類別為Converter的插件,同時分析插件類上的 @ConverterKeys 註解,獲取轉換器名稱,並建立名稱到插件實例的映射關系.
PatternParser識別到轉換器名稱的時候,會查找映射.

框架支持的所有轉換器如下:

有時我們需要對特定的轉換器進行特殊的配置,如:給DatePatternConverter配置時間格式,這個時候需要通過選項字元串配置.
PatternParser會提取模式字元串中的所有選項,保存在一個List<String>中,每個{}包裹的內容作為一個選項.
當創建轉換器時,框架會自動掃描轉換器類中聲明的靜態工廠方法newInstance,同時支持兩種可選的形參,一種是Configuration,另一種String[]則會注入選項列表.
選項列表的識別由不同的轉換器各自定義.

最後,以一個實際的例子解釋配置:
日誌會輸出時間,類名,方法名,消息以及一個換行符.
同時,我們給DatePatternConverter指定了了時間格式,並且限制全限定類名最小長度為5,右截斷,最大為10,左對齊.

管理器的職責主要是控制目標輸出流,以及把保存在ByteBuffer位元組緩沖區中的日誌序列化結果,輸出到目標流中.
如:RollingFileManager需要在每次追加日誌之前,進行滾動檢查,如果觸發滾動還會創建新的文件輸出流.
manager繼承體系如下:

過濾器的核心職責就是對 LogEvent 日誌事件進行匹配,匹配結果分為匹配和不匹配,結果值有3種:接受,拒絕,中立.可由用戶自定義匹配和不匹配的行為結果.

所有實現了 Filterable 介面的組件都可以引用一個過濾器進行事件過濾,包含 LoggerConfig 和 AppenderControl 等.

框架實現的過濾器如下:

『貳』 ExtJS是什麼,一位學長說的,對這個從未聽說

1.extja是什麼?
答: ExtJS是一種主要用於創建前端用戶界面,是一個與後台技術無關的前端ajax框架。
功能豐富,無人能出其右
無論是界面之美,還是功能之強,ext的表格控制項都高居榜首。
單選行,多選行,高亮顯示選中的行,推拽改變列寬度,按列排序,這些基本功能咱們就不提了。
自動生成行號,支持checkbox全選,動態選擇顯示哪些列,支持本地以及遠程分頁,可以對單元格按照自己的想法進行渲染,這些也算可以想到的功能。
再加上可編輯grid,添加新行,刪除一或多行,提示臟數據,推拽改變grid大小,grid之間推拽一或多行,甚至可以在tree和grid之間進行拖拽,啊,這些功能實在太神奇了。更令人驚嘆的是,這些功能竟然都在ext表格控制項里實現了。
呵呵~不過ext也不是萬能的,與fins的ecside比較,ext不能鎖定列(土豆說1.x里支持鎖定列,但是2.0里沒有了,因為影響效率。),也沒有默認的統計功能,也不支持excel,pdf等導出數據。另外fins說,通過測試ecside的效率明顯優於ext呢。:)
[編輯本段]Ext發展史
1、第一隻「出海」的YUI-Ext只是作者Jack打算對基於BSD協議的Yahoo!UI庫進行自定義的擴展,但後來一度風頭蓋過其父輩YUI,足以說明 大家對它的熱情,很多人把它投入項目人並不十分了解它。分析人士打了一比喻:就好比尚未謀面, 並不了解一個人的家庭、教育、品行等背景,只因為他有一副精緻漂亮的外觀,就對其陷入了瘋狂的傾慕之中。因此分析人士建議,在投入項目前,要認真仔細地了 解EXT的內在原理和與其他Ajax庫不同地方。
2、在2006年初 ,Jack Slocum(傑克斯·洛克姆 ) 就一套公用設施擴建為Yahoo! User Interface (YUI) 庫而工作。這些擴展很快組織成一個獨立的庫代碼並以」 yui-ext」 的名義下發布。
3、在2006年秋天,Jack發行了版本為0.33的yui-ext,而最終被證明為最後版本的代碼,根據這名字(下開放源代碼DSB許可)。在年底之前,這個庫已大受歡迎, 名字被簡化為Ext,反映了它作為一個框架的成熟和獨立。
該公司成立於2007年初,Ext現在為雙執照,使用LGPL和一個商業執照。
4、在2007年4月1日,發布1.0正式版。
5、直至今日(2008年4月1日)ExtJS已發展涵蓋美國、日本、中國、法國、德國等全球范圍的用戶,現在的版本為Ext-3.0
6、官方在2009年4月14-16日的首次Ext Conference中發布了Ext的3.0 RC版本。
7、2009年5月4日,Ext的3.0 版本發布。
[編輯本段]什麼是EXT
1、ExtJS可以用來開發RIA也即富客戶端的AJAX應用,是一個用javascript寫的,主要用於創建前端用戶界面,是一個與後台技術無關的前端ajax框架。因此,可以把ExtJS用在.Net、Java、php等各種開發語言開發的應用中。ExtJs最開始基於YUI技術,由開發人員JackSlocum開發,通過參考JavaSwing等機制來組織可視化組件,無論從UI界面上CSS樣式的應用,到數據解析上的異常處理,都可算是一款不可多得的JavaScript客戶端技術的精品。
2、Ext的UI組件模型和開發理念脫胎、成型於Yahoo組件庫YUI和Java平台上Swing兩者,並為開發者屏蔽了大量跨瀏覽器方面的處理。相對來說,EXT要比開發者直接針對DOM、W3C對象模型開發UI組件輕松。
[編輯本段]ExtJs UI Engine簡介
ExtJs初期僅是對Yahoo! UI的對話框擴展,後來逐漸有了自己的特色,深受網友的喜愛。 發展至今, Ext除YUI外還支持Jquery、Prototype等的多種JS底層庫,讓大家自由地選擇。該框架完全基於純Html/CSS+JS技術,提供豐富的跨瀏覽器UI組件,靈活採用JSON/XML數據源開發,使得服務端表示層的負荷真正減輕,從而達到客戶端的MVC應用!
ExtJs支持多平台下的主流瀏覽器 Internet Explorer 6+ FireFox 1.5+ (PC, Mac) Safari2+、Opera9+。在使用的廠家包括IBM、Adobe、Cisco和更多。ExtJs官方網站www.extjs.com
[編輯本段]Ajax主流框架與ExtJS
JQuery、 Prototype和YUI都屬於非常核心的JS庫。雖然YUI,還有最近的JQuery,都給自己構建了一系列的UI器件(Widget),不過卻沒有一個真正的整合好的和完整的程序開發平台。哪怕是這些低層的核心庫已經非常不錯了,但當投入到真正的開發環境中,依然需要開發者做大量的工作去完善很多缺失之處。而Ext就是要填補這些缺口。主流開源框架中只有Dojo像Ext一樣,嘗試著提供整合的開發平台。相比Dojo這個出色的工具包,我們認為 Ext能提供一個粘合度更高的應用程序框架。Ext的各個組件在設計之時就要求和其它Ext組件組合一起工作是無縫合作的。這種流暢的互通性,離不開一個緊密合作的團隊,還必須時刻強調設計和開發這兩方面目標上的統一,而這點是很多開源項目未能做到的。從構建每一個組件開始,我們始終都強調組件的外觀、性能、互通性和可擴展性,而我們認為組件已經達到了這幾點的要求。
Ext絕對可以單獨使用。實際上,除了有特定的要求,推薦單獨使用Ext,這樣的話文件佔位更小,支持和整合也更緊密。我們也支持與jQuery、 YUI或Prototype整合使用,作為低層庫的角色出現,以提供處理各種核心的服務,如DOM和事件處理,Ajax連接和動畫特效。使用整合方式的一個原因是它們已具備了一些特定的器件而Ext並沒有原生支持——像YUI的History控制項便是一個典型的例子。這時,Ext需要依賴YUI這個庫的底層來實現History控制項,這樣一來的話也可免去Ext自身底層庫,從而減少了整個程序的內存佔用。另一個使用整合方式的原因是,對於許多已在使用其他底層庫的程序,你可能希望逐步加入Ext。總之,如果已經有了其他庫,Ext可已利用它們。我們的宗旨是為用戶提供各種可能性和性能上的優化。而事實是,只要實現了相對應的底層庫介面,為任意一個框架添加上適配器是沒有問題的——人們可以輕松地將Dojo、Moo、Ajax.NET,或其它JS庫轉變為 Ext的底層。
Ext從2.x開始收費,這給他的應用前景帶來一些問題。不過對國內開發人員的影響不大,畢竟是客戶付款。
[編輯本段]Ext學習及應用經驗小結
一、理解Html DOM、Ext Element及Component
要學習及應用好Ext框架,需要理解Html DOM、Ext Element及Component三者的區別。
Ext是基於Web的富客戶端框架,其完全是基於標准W3C技術構建設的,使用到的都是HTML、CSS、DIV等相關技術。Ext最傑出之處,是開發了一系列非常簡單易用的控制項及組件,我們只需要使用這些組件就能實現各種豐富多彩的UI的開發。
無論組件有多少配置屬性、還是事件、方法等等,其最終都會轉化為HTML在瀏覽器上顯示出來,而每一個HTML頁面都有一個層次分明的DOM樹模型,瀏覽器中的所有內容都有相應的DOM對象,動態改變頁面的內容,正是通過使用腳本語言來操作DOM對象實現。
僅僅有DOM是不夠的,比如要把頁面中的某一個節點移到其它位置,要給某一個節點添加陰影效果,要隱藏或顯示某一個節點等,我們都需要通過幾句 javascript才能完成。因此,Ext在DOM的基礎上,創建了Ext Element,可以使用Element來包裝任何DOM,Element對象中添加了一系列快捷、簡便的實用方法。
對於終端用戶來說,僅僅有Element是不夠的,比如用戶要顯示一個表格、要顯示一棵樹、要顯示一個彈出窗口等。因此,除了Element以外,Ext 還建立了一系列的客戶端界面組件Component,我們在編程時,只要使用這些組件Componet即可實現相關數據展示及交互等,而 Component是較高層次的抽象,每一個組件在渲染render的時候,都會依次通過Element、DOM來生成最終的頁面效果。
在使用Ext開發的應用程序中,組件Component是最高層次的抽象,是直接給用戶使用的,Ext Element是Ext的底層API,主要是由Ext或自定義組件調用的,而DOM是W3C標準定義的原始API,Ext的Element通過操作DOM 來實現頁面的效果顯示。
在Ext中,組件渲染以後可以通過訪問組件的el屬性來得到組件對應的Element,通過訪問Element的dom屬性可以得到其下面的DOM對象。另外,我們可以通過通過Ext類的快捷方法getCmp、get、getDom等方法來得組件Component、Ext元素Element及DOM節點。比如:
var view=new Ext.Viewport();//創建了一個組件Component
view.el.setOpacity(.5);//調用Element的setOpacity方法
view.el.dom.innerHTML="Hello Ext";//通過Element的dom屬性操作DOM對象
再看下面的代碼:
var win=new Ext.Window({id:"win1",title:"我的窗口",width:200,height:200});
win.show();
var c=Ext.getCmp("win1");//得到組件win
var e=Ext.get("win1");//根據id得到組件win相應的Element
var dom=Ext.getDom("win1");//得到id為win1的DOM節點
二、熟悉ext組件體系
Ext2.0對整個框架進行了重構,最為傑出的是推出了一個以Component類為基礎的組件體系,在Component類基礎上,使用面向對象的方法,設計了一系列的組件及控制項。因此,要能游刃有餘地使用Ext,熟悉Ext組件體系是最基本的。
在《ExtJS實用開發指南》中,有如下面一幅組件圖:
通過組件結構圖我們可以一目瞭然的看出整個Ext組件繼承及組成體系,當使用一個組件的時間,了解他的繼承體系,這樣可以便於我們掌握組件的各種特性。
三、掌握核心控制項
控制項其實也是組件,比如用於顯示樹信息的TreePanel、用於顯示表格的GridPanel及EditorGridPanel,還有代表應用程序窗口的Ext.Window等都屬於Ext控制項。在使用Ext的時候,一定要掌握一些核心控制項,特別是處於基類的控制項。比如上面提到的幾個控制項,他們都是繼承於面板Panel,所以我們要重點掌握面板這個核心控制項的特性。比如面板由以下幾個部分組成:一個頂部工具欄(tbar)、一個底部工具欄(bbar)、面板頭部(header)、面板尾部(bottom)、面板主區域(body)幾個部分組成。面板類中還內置了面板展開、關閉等功能,並提供一系列可重用的工具按鈕使得我們可以輕松實現自定義的行為,面板可以放入其它任何容器中,面板本身是一個容器,他裡面又可以包含各種其它組件。只要掌握了Panel的應用,那麼學習TreePanel、Window等就會變得簡單得多。
同樣的道理,對於Ext的表單欄位來說,不管是ComboBox,NumberField、還是DateField,他們其它都是 Ext.form.Field類的子類,在他上面定義了表單欄位的各種基本操作及特性。在學習使用表單欄位組件時,一定要重點研究Field這個類,掌握他的主要方法、事件等,就能有助於更好的學習使用其它的欄位。
四、學習及研究示例
由於javascript語言非常靈活,不像靜態強類型語言(比如Java)那樣有固定的代碼設計模式,而往往是不同的人就有不同的編程風格。在實際應用開發中,只有見多識廣,才能在自己的在腦中建立一個開發庫。
學習別人的示例對於我們開發幫助會非常大,示例包括基本組件的應用、綜合應用等多個方面。在此,簡單推薦幾個。
1、Ext官方示例,在ext項目下載包的examples目錄中,包括各個控制項的基本應用演示,同時還有一些比較復雜的組合示例,有簡有繁,非常適合初學者認真研究。
2、Vifir推出的示例,Vifir推出的一些示例主要包括兩類,一種是開源的示例應用,另外一種是針對VIP用戶的實用示例。開源的示例主要是指 wlr單用戶blog系統,這個一個集合了前後台技術的ext綜合示例,而針對VIP用戶的實用示例則是可以作為開發骨架或擴展組件的示例。
3、其它示例,在ext社區中還有很多比較優秀的ext應用示例,有些只是一個應用演示,雖然沒有提供源碼下載,但我們可以直接下載引用的js文件來得到這些示例的ext應用代碼,同樣能取起到非常好的學習效果。
五、多運用
Ext看起來是非常簡單的東西,稍有點編程知識的人,按照《ExtJS實用開發指南》中的入門指南,半小時就能學會使用Ext。然而,當准備使用Ext開發一個項目時,卻不知道從何處入手,或者是在使用Ext的時候,出了一點小問題自己不知道該如何解決。編程是一門實踐性的科學,僅僅靠看書、看別人寫的代碼是遠遠不夠的,因此,必須多做實踐才行,只有通過不斷的練習,大量的使用,才能對Ext的組件特性、事件、事件處理機制以及與伺服器端交互介面等深入的掌握,只有多做運用,深入了解ext的組件的工作原理及機制,才能編寫出高級的Ext的應用。
六、熟讀Ext項目的源代碼
如果要想深入應用Ext,那麼閱讀Ext項目的源代碼這是必不可少的環節,Ext的代碼質量非常高,通過閱讀他的代碼我們可以更加深刻的了解 javascript面向對象編程,Ext代碼中包含了很多高級的js技巧以及設計模式。在使用Ext的過程中,我們經常根據項目的需要對Ext組件進行擴展,設計自己的組件或控制項,而如何實現一個自定義的Ext組件,我們可以從Ext的各個組件源代碼中找到答案。
Ext的源代碼在Ext項目的source目錄。讀Ext源碼,並不一定非要從某一個地方開始,而組件核心代碼Component.js、容器組件代碼 Container.js、面板Panel.js等這些是必看的; core目錄中的Element.js、Ext.js等也是必看的。當需要從一個控制項進行擴展的時候,最好能簡單看一看這個控制項的源代碼。
2.extjs應該很少應用吧 我做jsp的,從來就沒有用過這些東西·

『叄』 Eclipse怎麼看ExtJS源碼

Eclipse查看ExtJS源碼的方法
1、 首先把extjs/src/debug.js文件引入所要調試的頁面
2、 在需要調試的地方輸入以下語句即可
Ext.log(『This is a ExtJs debugger』);
3、 運行頁面時,凡是在添加Ext.log信息的頁面下方EXT都會自動生成調試信息,並且顯示在CONSOLE控制台中,類似eclipse的CONSOLE。另外在控制台右側窗口中輸入要執行的代碼,點擊【run】可以查看運行結果,比如Ext.getCmp(『comId』).getValue();
4、 ExtJs調試控制台 console默認是渲染到body下,如果頁面本身渲染的區域覆蓋住了調試控制台(用該組件Ext.Viewport時可能會覆蓋),則可以動態的修改console渲染的位置,可以修改源碼debug.js。在代碼
cp.render(Ext.getBody());處可以修改為以下
cp.render(Ext.get('debug'));//debug為頁面中dom元素

『肆』 ARouter源碼分析

Annotation Processing Tool,自定義註解處理器。
搞Android的基本上都知道這個吧。許多第三方庫都使用了APT去實現自己的功能,比如butterknife,比如X2C,比如我們要講的ARouter。
其基本做法是:

一般是自定義gradle Transform + ASM,實現AOP,可以在編譯期修改project和第三方依賴庫中的class文件(比如ARouter源碼中的arouter-gradle-plugin模塊),與APT主要是生成.java文件不同,ASM操作的是.class文件。
自定義gradle Transform功能很強大,可以與ASM結合,修改.class,也可以操作資源文件(比如統一壓縮圖片,轉png大圖為webp等)。
至於ASM,基於修改.class文件,我們即可以用ASM來插樁統計方法耗時,也可以用來實現自動化埋點,甚至是修改第三方lib中的crash...

使用方法可以看 ARouter 。
帶著問題看源碼,這里主要的問題是:

ARouter的核心方法。

這個方法算是核心中的核心了。
其實也只做了兩件事情

總的來說,只幹了一件事情,掃描所有的dex文件,找到com.alibaba.android.arouter.routes包下的所有文件並返回。這里的操作都是耗時操作。
但是com.alibaba.android.arouter.routes包下都是什麼文件呢?
比如:

比如:

比如:

比如:

這些都是APT生成的輔助類。

①項目編譯期,通過APT,生成輔助類(所有的輔助類包名都是com.alibaba.android.arouter.routes)
包括

②ARouter#init初始化的時候,掃描dex文件,找到①生成的輔助類文件(也即是包com.alibaba.android.arouter.routes下的文件),放到routerMap中

注意,這里沒有實例化IRouteGroup,IRouteGroup的信息都在IRouteRoot中,這樣做的目的是為了實現分組route的載入,用到了哪個group的route的信息,才會載入這個group的信息,沒用到就不載入。這里可以仔細想想IProviderGroup/IInterceptorGroup/IRouteGroup的區別。
該方法執行完了以後,

至此,就完成了初始化路由表的操作。
我們回過頭來瞄一眼ARouter#init,裡面初始化路由表以後,執行了_ARouter#afterInit

這一句看著很熟悉。

頁面路由跳轉/IProvider/攔截器都是ARouter.getInstance().build("/test/activity").navigation()這種形式的話,我們就先從攔截器interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();開始分析吧。

雖然這里我們是想看攔截器的實現,但是要明確一點:InterceptorServiceImpl是IProvider的實現類,獲取InterceptorService也就是獲取一個IProvider。有一點繞,簡單來說,ARouter使用一個IProvider來實現攔截器的初始化。
後面的邏輯就變成了獲取一個IProvider上了。

也即是ARouter.getInstance().build("/arouter/service/interceptor").navigation()方法中,ARouter.getInstance().build("/arouter/service/interceptor")做的事情就是創建一個Postcard,其path是"/arouter/service/interceptor",group是"arouter".

簡單來說,這里做的事情有

注意addRouteGroupDynamic(postcard.getGroup(), null)這個方法,通過groupName去groupIndex中查找,那"arouter"對應的是誰呢?正是ARouter$$Group$$arouter.class。
反射創建ARouter$$Group$$arouter對象,並執行ARouter$$Group$$arouter#loadInto方法

現在我們回過頭來繼續看LogisticsCenter#completion

總結一下LogisticsCenter#completion方法做了啥:

以ARouter.getInstance().build("/arouter/service/interceptor").navigation()舉例說明就是:

init方法做的事情很單一,就是一次性實例化全部的攔截器,存到 Warehouse.interceptors中。(想想為什麼要這么做?)
這樣,ARouter.getInstance().build("/arouter/service/interceptor").navigation()就分析完了,ARouter#init的時候,會創建所有的攔截器實例。ARouter.getInstance().build("/arouter/service/interceptor").navigation()方法返回的是InterceptorServiceImpl的實例。

另外,_ARouter#navigation(Context, Postcard, int, NavigationCallback)方法的最後,調用了_ARouter#_navigation

方法看著長,內容卻很簡單:

這樣, ARouter#init 就分析完了, 總結 一下:

另外使用ARouter.getInstance().build("path").navigation()方法 獲取IProvider的流程 如下:

Activity跳轉的流程如下:

至此,我們回答了問題1/問題2和問題4.
下面我們來看下剩下的問題
問題3:攔截器是如何生效的?
我們可以看看_ARouter

執行_ARouter#navigation的時候,執行了interceptorService.doInterceptions方法,前面我們已經知道,執行了interceptorService實際上是InterceptorServiceImpl。

這里一個一個調用攔截器,如果有攔截器攔截,就中斷調用,否則,調用下一個攔截器進行攔截。

所以, 攔截器 總結如下

最後,我們來看下最後一個問題。
問題5 ARouter的Gradle Plugin做了哪些優化?
該問題的關鍵是LogisticsCenter#loadRouterMap

上面的是gradle plugin修改之前的,下面的loadRouterMap是gradle plugin修改之後的。

瞄一眼register方法我們就能明白,這還是之前的那一套,跟不使用gradle plugin不同的地方在於,這里不需要掃描dex去找IRouteRoot/IInterceptorGroup/IProviderGroup,在編譯期,gradle plugin就已經找到了這些,然後生成新的loadRouterMap方法。

『伍』 Cesium 50個實例集合,講解、分析(內附源碼)

為方便快速測試斗橋 Cesium Demo使用,添加了一些演示demo並且提供了webpack打包的示例。目前整理了20個demo,後面會對demo進行講解。

詳情源碼連接:

Cesium 50個實例集合,講解、分析(內附源碼)

示例概要說明:

1.Draw.js 動態繪制 點、線、面

2.Scanning.js 一個簡單的掃描功能

3.Spline.js 樣條插值

4.HeightProperty.js 一個類似淹沒分析的效果

5.VectorTile.js 矢量切片載入

6.Ellipsoids.js 圓特效

7.Sensor.js 感測器,可設置角度,位置等空液猛

8.PolylineArrow.js 動態線效果

9.VolumesCZML.js 載入czml文件 支持感測器等動畫特效

10.VolumesApi.js VolumesApi 調用效果

11.Fly.js 繞點飛行

12.Radar.js 氣象雷達動態圖埋態

13.VisibleAnalysis.js 通視分析

14.EagleEye.js 鷹眼地圖

15.Measure.js 測量

16.Translucency.js 地球半透明,可做地下管線、礦山項目

17.Interior.js 地球內部,結合VectorTile.js會出很牛的效果

18.3dtiles載入

19.可視域分析_3DTiles

20.站心坐標轉WGS84

操作說明:

1.npm初始化第三方庫

npm install

2.在根目錄創建文件夾,文件夾名稱為「ThirdParty」 。

3.將根目錄下「node_moles\cesium\Build\Cesium」拷貝到「ThirdParty」 下。

4.編譯

npm run build

5.運行

npm run start

註:可以不要「2」、「3」步驟的,只是為了初學者能更快的找到源碼位置。



          

『陸』 HttpRunner2.x源碼分析——生成報告

在 api.py 中的run_tests函數中,httprunner執行測試用例並生成報告

api.py的_aggregate函數:

得到測試結果匯總後,通過 report.py 的 stringify_summary 函數將測試匯總串化,以便轉儲json文件並生成html報告。

串化測試匯總後,通過 report.py 的 render_html_report 函數生成html報告

httprunner使用jinja2生成測試報告,下文簡單介紹jinja2的用法,想要更深入了解請查看:

在jinja2中有3中語法:

過濾器相當於jinja2中的內置函數,可以對變數進行相應的處理,常用的過濾器有:

過濾器用法:在豎明變數後使用管道 | 調用,可鏈式調用

for循環由於迭代python中的列表和字典

宏相當於jinja2的自定義函數,定義宏的關鍵字是macro,後接宏的名稱和參數

調用宏

jinja2中最強大的部分就是模板繼承。模板繼承允許我們創建一個基本(骨架)文件,其他文件從該骨架文件繼承,然後針對自己需要的地方進行修或或改。

jinja2的骨架文件中,利用block關鍵字表示其包涵的內容可以進行修改。

以下面的骨架文件base.html為例:

jinja2模塊中有一個名為Enviroment的類,這個類的實例用於存儲配置和全局對象,然後從文件系統或其他位置中載入模板。

大多數應用都在初始化的時候撞見一個Environment對象,並用它載入模板。Environment支持兩種載入方式:

使用包載入器來加余團告載文檔的最簡單的方式如下:

其中:

文件系統載入器,不需要模板文件存在某個Python包下,可以直接訪問系統中的文件。

『柒』 RefreshScope源碼分析

一、 屬性
eager 默認為true,會進行refresh范圍內的全部bean進行提前實例化

二、 方法
refresh方法

發送RefreshScopeRefreshedEvent事件;
EventListener監聽方法

重新創建Bean對象鬧輪旁;

這個是核心的Bean處理類,主要定義了Bean的生命周期信息,Bean創建的工廠信息,以及Bean信息定義的緩存,桐穗除外還定義了Bean實例化前的動態修改bean信息的方法,實現當監聽到配置信息更新事件後能夠從緩存獲取Bean的定義信息,對需要重新修改bean定義的進行動態銷毀和重建;

BeanLifecycleWrapper
包裝bean生命液橡周期的包裝類,主要持有了ObjectFactory,利用其進行Bean對象的創建;

BeanLifecycleWrapperCache
BeanLifecycleWrapper的緩存,提高bean信息定義的獲取效率;

*BeanFactoryPostProcessor *
BeanFactoryPostProcessor的主體是BeanFactory,並且該介面中只定義了一個方法,其將會在ApplicationContext內部的BeanFactory載入完bean的定義後,但是在對應的bean實例化之前進行回調。所以通常我們可以通過實現該介面來對實例化之前的bean定義進行修改。

BeanFactoryPostProcessorBean(工廠的後置處理器)
在bean真正實例化前,通過注入的BeanFactory對上下文動態修改

(Bean注冊器的後置處理器)
更早於BeanFactoryPostProcessor動態處理上下文中的BeanDefinition信息

『捌』 Reference 和 Reference queue 精髓源碼分析

每個Reference狀態列表是Active、Pending、Enqueued、Inactive (本文也將基於以下這四種狀態做出源碼解讀)

狀態間主要的標識:
用Reference的成員變數queue與next(類似於單鏈表中的next)來標識

有了這些約束, GC 只需要檢測next欄位就可以知道是否需要對該引用對象(reference)採取特殊處理

什麼特殊處理?
GC在狀態active發送變化時,會主動把 weakReference中的 reference置null,PhantomReference 中的 reference 無視 (PhantomReference的get方法重寫返回null,可能就因為這原因就沒有置null了),並給next賦值this,以及pending等。(別問我為啥,測出來的。。。。培訓出來就這水平了)

描述:
active 狀態下的reference會受到GC的特別對待,GC在發現對象的可達性變成合適的狀態後將變更reference狀態,具體是變更為pending還是Inactive,取決於是否注冊了 queue

特點:

源碼分析:

描述:
pending-Reference列表中的引用都是這個狀態。
它們等著被內部線程ReferenceHandler處理(調用ReferenceQueue.enqueue方法)
沒有注冊的實例不會進入這個狀態!

特點:

源碼分析:

3.似乎明白了 ReferenceQueue.ENQUEUED 的含義

描述:
調用ReferenceQueue.enqueued方法後的引用處於這個狀態中。
沒有注冊的實例不會進入這個狀態。

特點:

源碼分析:
可以看出 整體是一種先進後出的棧結構。head作為棧頭。r.next指向成員變數 head,如果head為null,那麼就指向自己(為了後面的壓棧好找元素)

描述:
最終狀態,處於這個狀態的引用對象,狀態不會在改變。

兩種途徑到這個狀態:
1.referenceQueue 調用 reallyPoll ,
2.不注冊 referenceQueue,reference state變化時。

特點:

源碼分析:

引用:
https://liujiacai.net/blog/2015/09/27/java-weakhashmap/#%E5%BC%B1%E5%BC%95%E7%94%A8%EF%BC%88weak-reference%EF%BC%89

『玖』 源碼分析->一個應用到底有幾個Context

相信很多人都知道是這樣計算的,那到底為什麼是這樣呢?

源碼分析基於Android28源碼

什麼是Context呢?可以理解為上下文、運行環境,當需要獲取資源、系統服務以及啟動Activity、Service用到,也可以通過它跟系統交互。

通過以下繼承關系可以看出,Activity是繼承ContextWrapper

ContextWrapper內部有一個Context類型的成員變數mBase

mBase是通過attachBaseContext()方法賦值

是創建Activity的關鍵,
主要工作
(1)createBaseContextForActivity()內部實例化ContextImpl 對象;
(2)mInstrumentation.newActivity()內部通過反射實例化Activity對象;
(3)activity.attach()內部會調用attachBaseContext()方法給mBase對象賦值;

通過以下繼承關系可以看出,Application是繼承ContextWrappe

是創建Application的關鍵,
主要工作:
(1)ContextImpl.createAppContext()實例化ContextImpl ;
(2)mActivityThread.mInstrumentation.newApplication(),內部通過反射實例化Application,並把appContext傳遞過去,通過attach()方法給mBase賦值;

跟Activity類似就不再做分析。
經過分析發現:
1.每個Activity,Service,Application都有一個ContextImpl 類型的成員變數mBase,ContextImpl是Context的實現類。
2.細心的讀者可能發現,Activity,Service,Application都是繼承Context,其實他們本身是一個Context,也都實現了Context的抽象方法,
那麼一個Activity是否就擁有兩個Context呢?
是不是

這樣計算比較合適呢?

下面看下Context中常用的三個方法,

ContextImpl繼承Context,並實現了這三個方法,

Activity間接繼承Context,主要是在ContextWrapper實現了以上三個方法,從源碼中可以看出,最終還是調用了ContextImpl的實現。

下圖可以看出這幾個的關系,ContextWrapper顧名思義就是Context的包裝類(有ContextImpl的成員變數),並且實現了Context,這是一種裝飾者設計模式。當在Activity中調用getAsset()時,其實最終是調用mBase的getAsset()。

Activity間接繼承了Context,是為了擁有跟ContextImpl一樣的功能,但真正起作用的是mBase這個成員變數,所以一個Activity其實就只有一個Context起作用,那就是ContextImpl類型的mBase。

這種計算方法應該是沒有問題呢。
或許有人有這樣的疑問,一個應用不是只有一個Application嗎,為什麼計算公式是加上Application個數?單進程應用來說,一個應用確實只有一個Application,而多進程應用,那麼一個應用就有多個Application,所以應該說一個應用有一個或多個Application,一個進程有一個Application。

另外其他關於Context的常見面試題
1.Activity的this跟getBaseContext區別。
前者是Activity對象本身,後者是通過attachBaseContext傳入的ContextImpl對象mBase,兩者功能是一樣的,通過this最終還是會調到mBase對象中。
2.getApplication和geApplicationContext區別。
兩者都是返回Application對象,前者是Activity和Service裡面的方法,後者是Context中定義的方法。
3.應用組件的構造,onCreate、attachBaseContext的執行順序。
先是組件構造化,接著attachBaseContext,傳入ContextImpl對象,最後是onCreate方法。
4.談談你對Context的理解
先是Context的作用,然後是有幾種Context,Application、Service、Activity的Context有什麼區別以及繼承關系,
最後是mBase變數是如何實例化的。

以上分析有不對的地方,請指出,互相學習,謝謝哦!

『拾』 ExtJS開發實戰的目錄

《extjs開發實戰》
第 1 章 入門 1
1.1 何謂extjs 2
1.2 cakephp 5
1.3 部署開發環境 5
1.3.1 部署伺服器 6
1.3.2 部署cakephp 6
1.3.3 部署extjs 10
1.4 開發工具 10
1.5 調試與性能評估工具 10
1.5.1 firebug 插件 10
1.5.2 chrome的javascript控制台 12
1.5.3 性能評估與數據監控 12
1.6 小結 14
第Ⅰ部分 基礎架構
第 2 章 extjs 101 17
2.1 javascript的面向對象 18
2.1.1 創建類 18
2.1.2 定義類方法與類屬性 21
2.1.3 類的繼承 22
.2.1.4 extjs在面向對象方面的支持 26
2.1.5 實戰練習:預配置類 33
2.2 瀏談並慶覽器對象模型:bom 35
2.2.1 命名空間 36
2.2.2 用戶代理對象 38
2.2.3 歷史記錄對象 40
2.2.4 dom文件對象document 46
2.2.5 cookie 47
2.2.6 定時調用函數 48
extjs 開發實戰
第 3 章 dom與event 53
3.1 extjs對dom的支持 54
3.1.1 創建element實例 55
3.1.2 通過element創建dom節點 64
3.1.3 讀取/更新dom節點及屬性 72
3.1.4 domhelper與template、xtemplate 85
3.2 extjs對事件的支持 99
3.2.1 一切的開始——ext.ready() 100
3.2.2 注冊/移除事件處理程序 100
3.2.3 ext.eventmanager 102
3.2.4 阻止事件的進行與默認行為 103
3.2.5 ext.util.observable與自定義事件 104
3.3 實戰練習:畫布應用 110
第 4 章含握 好用的php框架——cakephp 119
4.1 cakephp的設計結構 120
4.2 自動化開發 122
4.3 cakephp基礎 130
4.3.1 cakephp的配置文件core.php 130
4.3.2 cakephp的基礎模板default.ctp 132
4.3.3 模型 139
4.3.4 控制器 141
4.3.5 視圖與視圖助手 146
4.4 實戰練習:登錄窗體 148
4.4.1 製作模型 149
4.4.2 編寫控制器 155
4.4.3 編寫頁面視圖 159
4.4.4 更改默認控制器 160
4.4.5 url前綴的應用 162
4.4.6 使用cake 2.*版本? 不,謝謝 163
4.4.7 下一步 164
第 5 章 ajax與數據驅動 165
5.1 ext.ajax與ext.data.connection 166
5.2 存儲對象 179
5.2.1 ext.data.store 181
5.2.2 讀取遠程數據 187
5.3 實戰練習:表格組件 195
第 6 章 component結構 199
6.1 component模型 200
6.2 常用組件 208
6.2.1 colorpalette 調色板 208
6.2.2 button按鈕 209
6.2.3 splitbutton按鈕 211
6.2.4 baseitem基礎選項 212
6.2.5 datepicker日期選擇面板 213
6.3 xtype神秘類型 214
6.4 實戰練習:自定義組件 218
第 7 章 container結構 223
7.1 container容器 224
7.2 panel容器 227
7.2.1 添加子組件/容器 229
7.2.2 移動子組件/容器 231
7.2.3 查找子組件/容器 234
7.2.4 刪除子組件/容器 238
7.2.5 頂層組件欄(tbar)與底層組件欄(bbar) 239
7.2.6 可折疊的panel 240
7.2.7 嵌套panel 241
7.3 viewport容器 244
7.4 window容器 246
7.5 buttongroup容器 250
7.6 button類似容器的用法 253
7.7 實戰練習:更實用的window類 254
extjs 開發實戰
第Ⅱ部分 視圖組件蔽伍
第 8 章 頁面布局 261
8.1 一切都從containerlayout開始 262
8.2 可讓組件大小隨容器改變的anchorlayout 263
8.3 可隨意擺放組件的absolutelayout 265
8.4 填滿容器的fitlayout 268
8.5 如手風琴般的accordionlayout 269
8.6 將組件以撲克牌方式擺放的cardlayout 271
8.7 表單布局formlayout 273
8.8 邊界布局borderlayout 274
8.9 水平布局hboxlayout與垂直布局vboxlayout 276
8.10 列布局columnlayout 276
8.11 表格布局tablelayout 278
8.12 混合布局 279
8.13 實戰練習:自定義布局 282
第 9 章 表單組件 287
9.1 表單容器formpanel與一般容器panel的差異 288
9.2 文本欄位 291
9.2.1 密碼欄位 294
9.2.2 文件上傳欄位 294
9.2.3 文本塊 295
9.2.4 數字欄位 296
9.2.5 欄位驗證 297
9.2.6 隱藏欄位 298
9.3 下拉菜單與自動完成 299
9.3.1 使用本地數據 299
9.3.2 遠程數據與下拉菜單 303
9.3.3 遠程數據與自動完成 307
9.3.4 聯動下拉菜單 308
9.4 wysiwyg文本編輯器 310
9.5 日期欄位 311
9.6 復選組件與單選組件 312
9.7 提交/讀取數據 313
9.8 欄位提示quicktips與quicktip317
9.9 美化表單 320
9.9.1 使用boxcomponent為表單添加自定義html內容 320
9.9.2 使用fieldset集合特定欄位 321
9.10 實戰練習:登錄表單 322
第 10 章 表格組件 329
10.1 gridpanel是如何組成的 330
10.2 創建gridpanel與數據排序 331
10.3 使用pagingtoolbar進行分頁 336
10.4 girdpanel與查詢 339
10.5 自定義繪圖器 342
10.6 通過selectionmodel與gridpanel交互 345
10.7 實戰練習:dtable 348
第 11 章 可編輯表格組件 355
11.1 創建editorgridpanel 356
11.2 更換欄位編輯器與數據交互 358
11.2.1 更換欄位編輯器 358
11.2.2 添加與刪除記錄 360
11.3 使用roweditor 363
11.4 數據的提交與回滾 365
11.4.1 commitchanges()與rejectchanges() 365
11.4.2 同步伺服器數據 367
11.5 使用datawriter 370
11.6 實戰練習:etable 373
第 12 章 dataview與listview 381
12.1 dataview 382
12.1.1 創建數據顯示樣式 382
12.1.2 創建store與xtemplate 383
12.1.3 創建dataview 385
12.1.4 讓dataview可分頁 386
extjs 開發實戰
12.2 listview 387
12.3 屬性設置表propertygrid 389
12.4 實戰練習:數據讀取 392
第 13 章 圖表組件 401
13.1 圖表底層的秘密 402
13.2 折線圖:linechart 405
13.2.1 繪制折線圖 405
13.2.2 修改提示信息 406
13.2.3 添加水平/垂直軸的標題 408
13.2.4 修改圖表風格 409
13.2.5 添加多個序列 411
13.3 柱形圖:columnchart與stackedcolumnchart 413
13.4 條形圖:barchart與stackedbarchart 415
13.5 圓餅圖:piechart 417
13.6 實戰練習:圖表應用 419
第 14 章 樹狀組件 425
14.1 使用靜態數據創建treepanel 426
14.2 讀取伺服器數據 428
14.3 操作節點 432
14.3.1 添加節點 432
14.3.2 刪除節點 438
14.3.3 編輯節點 441
14.3.4 查詢節點 442
14.3.5 排序節點 443
14.4 columntree 444
14.5 實戰練習:treeeditor 447
第 15 章 菜單與工具欄 453
15.1 創建菜單 454
15.1.1 菜單101 454
15.1.2 菜單事件 456
15.1.3 加入separator與textitem457
15.1.4 colormenu與datamenu 459
15.1.5 添加復選框 460
15.1.6 添加單選按鈕 462
15.2 使用上下文菜單 463
15.3 創建工具欄 465
15.4 實戰練習:復雜的菜單與工具欄組合 467
第 16 章 拖放——drag與drop 473
16.1 拖放的基礎知識 474
16.2 拖放操作的實現 476
16.2.1 注冊dom元素為dd 477
16.2.2 使用ddtarget注冊放置目標 478
16.2.3 使用ddproxy 484
16.3 實戰練習:將拖放與組件結合 487
16.3.1 dataview與拖放 487
16.3.2 treepanel與拖放 493
第 17 章 插件 495
17.1 繼承的限制 496
17.2 插件的實現 499
第 18 章 長路漫漫——extjs 4 503
18.1 類系統 504
18.1.1 定義類的新方式 504
18.1.2 動態讀取類定義與依賴性管理 508
18.1.3 混合屬性 513
18.1.4 靜態方法 515
18.1.5 自動生成變數的getter/setter方法 516
18.2 data 封包 517
18.2.1 model 517
18.2.2 proxy與store 523
18.3 panel、formpanel、gridpanel與window 537
18.3.1 panel組件 537
18.3.2 formpanel組件 539
extjs 開發實戰
18.3.3 gridpanel組件 541
18.3.4 window組件 543
18.4 圖表組件 545
18.4.1 area圖表 545
18.4.2 bar圖表 548
18.4.3 radar圖表 551
18.4.4 pie圖表 552
extjs 4後記 554
第Ⅲ部分 實戰案例
第 19 章 案例——記賬系統 557
19.1 系統需求分析 558
19.2 系統規劃 558
19.2.1 界面規劃 558
19.2.2 後台伺服器部署 560
19.3 系統實現 561
19.3.1 實現cakephp端 562
19.3.2 實現extjs界面 578
19.4 與cakephp結合 611
第 20 章 案例——人人網應用程序 615
20.1 系統功能分析 616
20.2 系統部署 618
20.3 封裝google maps api的類gmap 621
20.4 組合界面組件 629
20.4.1 定義geomappanel 629
20.4.2 定義functionmenu 630
20.4.3 定義georecordgridpanel 632
20.4.4 定義mainpanel 636
附 錄 學習與實現資源 645

熱點內容
scratch少兒編程課程 發布:2025-04-16 17:11:44 瀏覽:639
榮耀x10從哪裡設置密碼 發布:2025-04-16 17:11:43 瀏覽:368
java從入門到精通視頻 發布:2025-04-16 17:11:43 瀏覽:84
php微信介面教程 發布:2025-04-16 17:07:30 瀏覽:310
android實現陰影 發布:2025-04-16 16:50:08 瀏覽:793
粉筆直播課緩存 發布:2025-04-16 16:31:21 瀏覽:344
機頂盒都有什麼配置 發布:2025-04-16 16:24:37 瀏覽:212
編寫手游反編譯都需要學習什麼 發布:2025-04-16 16:19:36 瀏覽:812
proteus編譯文件位置 發布:2025-04-16 16:18:44 瀏覽:366
土壓縮的本質 發布:2025-04-16 16:13:21 瀏覽:592