標籤: 網頁設計公司

  • 一起玩轉微服務(4)——如何實施微服務

    一起玩轉微服務(4)——如何實施微服務

    一、如何實施微服務

    微服務是一種架構的理念,提出了微服務的設計原則,從理論為具體的技術落地提供了指導思想。
    實施微服務需要具備以下條件:

    • 計算和存儲資源能否快速的分配
    • 是否具備快速部署的能力,因為微服務每個服務都比較微小,所以不管是測試環境還是生產環境都需要快速部署的能力
    • 基本的監控,包括CPU、內存、網絡等
    • 標準化的RPC

    Spring Boot 是一套快速配置腳手架,可以基於 Spring Boot 快速開發單個微服務。
    Spring Cloud 是一個基於 Spring Boot 實現的服務治理工具包;Spring Boot 專註於快速、方便集成的單個微服務個體;Spring Cloud 關注全局的服務治理框架。
    Spring Boot / Cloud 是微服務實踐的最佳落地方案。
    當然,微服務的設計還對運維提出了更高的要求,如何進行自動構建,如何進行自動發布,對於應用程序的質量管理以及遇到峰值時如何通過橫向擴展、彈性伸縮對於整個技術團隊都提出了更高的要求。

    二、最流行6種微服務RPC技術

     

     

     

     

    開源 RPC 框架有哪些呢?

     

    一類是跟某種特定語言平台綁定的,另一類是與語言無關即跨語言平台的。
    跟語言平台綁定的開源 RPC 框架主要有下面幾種。

    • Dubbo:國內最早開源的 RPC 框架,由阿里巴巴公司開發並於 2011 年末對外開源,僅支持 Java 語言。
    • Motan:微博內部使用的 RPC 框架,於 2016 年對外開源,僅支持 Java 語言。
    • Tars:騰訊內部使用的 RPC 框架,於 2017 年對外開源,僅支持 C++ 語言。
    • Spring Cloud:國外 Pivotal 公司 2014 年對外開源的 RPC 框架,僅支持 Java 語言

    而跨語言平台的開源 RPC 框架主要有以下幾種。

    • gRPC:Google 於 2015 年對外開源的跨語言 RPC 框架,支持多種語言。
    • Thrift:最初是由 Facebook 開發的內部系統跨語言的 RPC 框架,2007 年貢獻給了 Apache 基金,成為 Apache 開源項目之一,支持多種語言。

    三、rest

    1. 什麼是REST

    REST是一種架構風格,指的是一組架構約束條件和原則。滿足這些約束條件和原則的應用程序或設計就是 RESTful。REST規範把所有內容都視為資源,網絡上一切皆資源。

    REST並沒有創造新的技術,組件或服務,只是使用Web的現有特徵和能力。 可以完全通過HTTP協議實現,使用 HTTP 協議處理數據通信。REST架構對資源的操作包括獲取、創建、修改和刪除資源的操作正好對應HTTP協議提供的GET、POST、PUT和DELETE方法。

    REST與RPC比較

    比較項        規範 REST RPC
    通信協議 HTTP 一般使用TCP
    性能
    靈活度

    高與低是對實現兩種規範框架的相對比較,但也不是絕對的,需要根據實際情況而定。

    都是網絡交互的協議規範。通常用於多個微服務之間的通信協議。

    2. REST與RPC應用場景

    REST和RPC都常用於微服務架構中。

    • HTTP相對更規範,更標準,更通用,無論哪種語言都支持http協議。如果你是對外開放API,例如開放平台,外部的編程語言多種多樣,你無法拒絕對每種語言的支持,現在開源中間件,基本最先支持的幾個協議都包含RESTful。

    RPC在微服務中的作用,RPC 框架作為架構微服務化的基礎組件,它能大大降低架構微服務化的成本,提高調用方與服務提供方的研發效率,屏蔽跨進程調用函數(服務)的各類複雜細節。讓調用方感覺就像調用本地函數一樣調用遠端函數、讓服務提供方感覺就像實現一個本地函數一樣來實現服務。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司“嚨底家”!

    ※別再煩惱如何寫文案,掌握八大原則!

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    聚甘新

  • Uber在英推出電動車隊,BYD、Nissan響應

    新式交通運輸公司Uber在英國倫敦發表了全球首支電動車車隊,並由中國比亞迪(BYD)、日商Nissan響應,分別提供E6和LEAF組成一支50輛電動車的車隊。這支車隊在8月31日正式上路,可有效減少當地空污;若反應良好,還會拓展到其他英國城市。

    倫敦市長Sadiq Khan曾承諾要將倫敦市轉型為全球最環保的城市,並積極採用低碳排放車款、設置電動車充電站。今年三月,由BYD和英國ADL聯手研發的五輛電動雙層巴士正式在倫敦上路,是全球首個電動雙層巴士車隊。

    另一方面,Uber也曾在南非、葡萄牙測試驗動車專案,並推出Uber Green實驗性服務。Uber車隊也曾採用Toyota Prius油電混和車,藉此降低行駛時的碳排放量。

    英國Uber總經理Jo Bertram表示,Uber希望能建立一個節能減碳的共乘交通模式,與Nissan、BYD的合作代表這個決心,也將是個起點。目前,英國的Uber大約有六成是油電混和車款,倫敦市對於電動車的接受度相對較高。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    聚甘新

  • 電動巴士開進太魯閣,花縣繼續推動綠能公車政策

    電動巴士開進太魯閣,花縣繼續推動綠能公車政策

    花蓮縣太魯閣客運公司今年繼續辦理增資,以採購新的電動巴士。自9月起,往來於花蓮市區、太魯閣、東華大學等地的公車路線,將有電動巴士陸續開始運行。

    花蓮縣政府的「綠能公車」政策於2014年核定太魯閣客運公司的301線、302線兩條公車路線上路,且須採用電動巴士運行。一開始因電動巴士品質不夠穩定,一度改租用柴油巴士,但受到反彈而停駛;之後在地方民代的協調下,301、302線規劃復駛,並透過增資採購7輛低底盤K9電動巴士車輛,重新展開電動巴士服務。

    太魯閣客運公司經理表示,本次採購的7輛K9電動巴士為台灣凱勝綠能科技所生產,車體採用全鋁合金打造,並配有緊急自動滅火系統、ABS防鎖剎車等。車輛搭載的電池為台灣長利科技的磷酸鋰鐵電池,每次充飽電的續航力可達250公里以上。

    K9巴士的性能佳,目前在苗栗客運、捷順交通、雲林客運、南台灣客運等公司都有同款車輛正在提供服務。太魯閣客運採購K9巴士時,為挑戰巴士的續航力,還安排一輛K9巴士直接從苗栗車體廠繞過北台灣、蘇花公路一路行駛到花蓮東華大學,總里程320.7公里,全程開冷氣;駛達目的地後,電池的電量還有43.9%之多。

    目前,301線已配合東華大學開學而正式復駛。太魯閣客運希望新城到天祥的302線也能在年底前復駛,預計將有6輛電動巴士投入服役。

    (照片來源:東華大學/太魯閣客運)

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司“嚨底家”!

    ※推薦評價好的iphone維修中心

    聚甘新

  • 特斯拉帶動電池需求,住友化學擬擴產四倍

    特斯拉(Tesla)雖然傳出供貨不及、營收下滑等問題,但仍明顯帶動全球市場對於電動車的關注與需求。看好電動車用鋰電池的需求量將繼續成長,日本住友化學(Sumitomo Chemical)計畫在2018年時將位於南韓的分隔膜(separator)產能擴增至2016年初水準的4倍。

    根據《日經》報導,電動車市場的擴大,直接推動電動車用鋰電池的供應鏈強度,從材料到電池包都成為產業關注的焦點。特斯拉的車用電池由日本Panasonic所提供,而Panasonic供應給特斯拉的電池所使用的分隔膜,則由住友化學供應。因應特斯拉打算在2018年將年產能提高到50萬輛、2020年增至100萬輛,住友化學預期Panasonic的分隔膜需求會在接下來暴漲,因此決定擴產。

    正極與負極材料、分隔膜、電解液是鋰電池的四大關鍵材料,且日廠佔有絕對的市佔率。除住友化學供應分隔膜給 Panasonic 之外,Toray也有供應分隔膜給Panasonic、LG Chem,且預計在2018年底時將產能提高70%。另一分隔膜廠商旭化成計畫在2020年底前倍增分隔膜產能,住友金屬礦山打算在近年將正極材料產能擴大兩倍、昭和電工則規畫在今年底前提高負極材料產能80%。

    MoneyDJ引用日本市調機構富士經濟的說法,認為全球電動車市場會在2020年左右急速擴大,到2035年時成長到567萬輛,較2015年飆漲近16倍之多。其中,又以中國、歐洲市場的成長幅度最為明顯。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

    ※教你寫出一流的銷售文案?

    ※超省錢租車方案

    聚甘新

  • 中國大陸公布電動車違規業者,市場趨緩?

    先前北京重金支持環保車,新能源車飆速成長,人人都想分杯羹。如今當局態度驟變、開始教訓業者,接連兩天公布違規廠商名單。北京政策大轉彎,新能源車恐怕會從生機蓬勃的春天一夕轉為料峭刺骨的寒冬。

    BusinessKorea、路透社報導,中國財政部8日懲處了至少五家車廠,指控他們的電動車和油電混合車計畫不實,非法取得人幣10億元補助,決定吊銷蘇州吉姆西客車製造(Suzhou Gemsea Coach Manufacturing)的生產執照,並對另外四家車廠處以罰款,其中包括中國第七大轎車廠奇瑞控股(Chery Holding)的子公司。

    專家指出,這表示中國新能源車政策出現劇變,中國企業工業協會(CAAM)副秘書長Xu Yanhua說,這對車業是一大打擊,對執法有重大影響。9日北京當局再次出擊,官媒中國證券報再公布了20家違規車廠,包括日本的日產汽車(Nissan)、韓國的現代汽車、中國的吉利汽車、江淮汽車(JAC)、比亞迪(BYD)子公司等。

    北京調查騙補,勢必會影響新能源車銷售,難以達到年度銷售70萬輛的目標。今年前八個月,新能源車僅售出24.5萬輛,和目標差距極大,當局又當頭澆下冷水,沒了補助誘因,車商更沒動力推出電動車,車市恐會驟然轉冷。

    台灣電動車概念股包括康普、F-貿聯、和大、F-乙盛、胡連、健和興、台達電等。

    北京政策急轉彎有跡可循,當局為了降低財庫負擔、促進技術發展,決定調整政策,未來擬降低補貼、拉高准入門檻,讓新能源車行業告別「野蠻生長」、迎來一輪優勝劣汰的洗牌。不過,這也意味著大陸目前超過200家的新能源車新創業者有超過9成5恐在兩年內被淘汰出局。

    大陸官營的人民日報8月27日報導,由於新能源車補貼政策的激勵和准入門檻較低,行業在快速發展的同時也產生不少問題,比如重複建設、低品質、同質化產品現象嚴重,甚至出現了企業騙補的情況。對此,財政部官員透露,近期將調整新能源汽車的補貼政策。中國已在去(2015)年超越美國成為全球最大新能源車(包括電動車、插電式油電混合車以及燃料電池車)市場。

    (本文內容由授權提供)

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※別再煩惱如何寫文案,掌握八大原則!

    網頁設計最專業,超強功能平台可客製化

    聚甘新

  • 推動電動車,中國要求加速住宅區充電設施建設

    為確保住宅區居民的電動車充電需求,中國國家發改委、能源局、工信不予鑄件部聯合發出通知,要求各地區加速推廣住宅區的電動車充電基礎建設,並須推動既有之住宅區停車位的電氣化改造。

    根據聯合通知,在既有停車位的改造方面,專用的固定車位需依照「一表一車位」之模式進行配套供電設施增加容量的改造,且每個停車位需配置適當的容量電能表。公用車位則需考量該區實際情形與電動車車主之充電需求,進行配套供電設施建設。

    北京政府亦將針對住宅區停車位的電氣化建設提供專項資金等政策支持。

    同時,聯合通知要求開始研究第三方充電服務企業、物業服務企業、車位產權方、業主委員會等多方共同參與住宅區充電基礎設施營運與市場化經營,並鼓勵導入集中改造、智慧充電管理、多用戶分時分享等營運模式,以提升營運水準。各地的主管部門亦可根據在地營運狀況推出合理的收費機制,以行程可永續經營的市場型態。

    該通知同時要求推動住宅區充電設施的保險配套工作,保險涵蓋範圍包括:設施製造商、營運業務方、企業、用戶個人等。

    中國將在京津冀魯、長江三角、珠江三角等三地的重點城市與各地能源發改委以及房地產主管部門合作推動示範性專案。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    南投搬家公司費用需注意的眉眉角角,別等搬了再說!

    ※教你寫出一流的銷售文案?

    聚甘新

  • 福斯推出概念電動車,續航力上看600公里

    福斯汽車(Volkswagen)因排氣造假醜聞而加速電動車研發腳步,不僅研發電動車平台MEB,更預計在今年9月底的巴黎車展上推出首輛由MEB平台打造的電動概念車。這款電動概念車的續航力據報導可達400~600公里。

    媒體報導,福斯這款即將面世MEB平台電動概念車,外觀較接近既有車款,大小類似Golf,空間則接近Passat。為維持價格合理,並未採用太多昂貴的輕量複合材質。

    值得注意的是,在NEDC標準測試下,這款概念車的續航力可達400~600公里之遠。優異的續航性能與合理定價,將有助提高消費者對產品的接受度。此外,這款概念車據稱已十分接近量產階段,預期會在2019年正式投產。

    MEB平台也會陸續研發出多款電動汽車,如Phaeton、Budd-e等。福斯計畫在2025年之前推出至少30款電動車款,並在2030年時將電動車銷售量提高到旗下總銷量的三分之一。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司“嚨底家”!

    ※別再煩惱如何寫文案,掌握八大原則!

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    聚甘新

  • 軟件架構的核心思想

    軟件架構的核心思想

    目錄

    • 前言
    • 一、軟件架構的定義
    • 二、軟件架構與設計
    • 三、軟件架構的幾個方面
      • 系統
      • 結構
      • 環境
      • 利益相關者
    • 四、軟件架構的結構特徵
      • 運行時結構
      • 模塊結構
    • 五、軟件架構的質量屬性
      • 可修改性
      • 可測試性
      • 可擴展性
      • 性能
      • 可用性
      • 安全性
      • 可部署性
    • 六、其他常見概念
      • 內聚
      • 耦合
      • 企業架構
      • 系統架構

    前言

    welcome to chenqionghe’s blog,架構能力其實更像是一種內功,需要我們不斷地去學習,讓我們用一張正能量的圖片開啟美好的學習生活,let’s do it~

    一、軟件架構的定義

    架構是一個系統的基本組織,涵蓋所包含的組件,組件之間的關係、組件與環境的關係,以及指導架構設計和演進的原則等內容

    二、軟件架構與設計

    軟件架構和軟件設計中都有“設計”的意思,但與後者相比,前者具有更高的抽象性和更廣的範圍

    • 軟件架構關注如何對系統中的結構和交互進行較高級別的描述,它關注的是那些與系統骨架相關的決策問題,例如:功能、組織 、技術、業務和質量標準等。
    • 軟件設計關注構成系統的部件或組件,以及子系統是如何組織的,關注的問題通常更接近代碼或模塊本身,例如:
      • 將代碼分成哪些模塊?如何組織?
      • 給不同的功能分配哪些類(或模塊)?
      • 對於類“C”應該使用哪種設計模式?
      • 在運行時對象之間是如何交互的?傳遞什麼消息?如何實施交互?

    三、軟件架構的幾個方面

    系統

    系統是以特定方式組織的組件集合,以實現特定的功能。
    軟件系統是其軟件組件的集合。一個系統通常可以劃分為若干個子系統。

    結構

    結構是根據某個指導規則或原則來組成或組織在一起的一組元素的集合,可以是軟件或硬件系統。
    軟件架構可以根據觀察者的上下文展示各個層次的結構

    環境

    軟件系統所在的上下文或環境對其軟件架構有直接的影響。
    這樣的上下因素可以是技術、商業、專業、操作等

    利益相關者

    任何對某個系統及其成功與否感興趣或關心的個體或團體,都是利益相關者。
    例如:架構師、開發團隊、客戶、項目經理和營銷團隊等

    四、軟件架構的結構特徵

    運行時結構

    在運行時創建的對象及其之間的交互方式經常決定部署架構。
    部署架構與可擴展性、性能、安全性和交互操作性等質量屬性密切相關

    模塊結構

    為了分解任務,如何拆分代碼並把代碼組織到模塊和包中,這與系統的可維護性和可修改性密切相關,因為

    • 在代碼組織過程中考慮到可擴展性的話,通常會將父類放在單獨定義好的具有恰當文檔和配置的包中,這樣就可以輕易地通過增加外部模塊進行擴展,而不需要處理太多的依賴關係
    • 對於那些依賴於外部或第三方開發者(庫、框架等)的代碼,通過會根據提供的安裝或部署步驟,從外部源手動或自動地獲取並補丁全部各種依賴。此類代碼還提供多種文檔(例如README、INSTALL)等,它們清楚地記錄了這些步驟

    五、軟件架構的質量屬性

    質量屬性是系統的可度量和可測試的特性,可用於評估系統在其指定環境中的非功能性需求方面的達成情況

    可修改性

    定義為對系統進行修改的容易程度,以及系統對理髮進行調整的靈活性。
    這是討論的修改不光是代碼的修改、部署的修改,而是任何層次上的修改。
    一般架構師對可修改性的興趣點如下:

    • 難點:對系統進行修改的難易程度
    • 成本:進行修改需要的時間和資源
    • 風險:任何與系統修改相關的風險

    代碼可讀性越強,其可修改性就越強,代碼的可修改性與可讀性成正比

    可測試性

    指一個軟件系統支持通過測試來檢測故障的程度。
    可測試性也可以認為是一個軟件系統向最終用戶和集成測試隱藏了多少bug
    一個系統的可測試性越好,它能隱藏的bug就越少。

    可擴展性

    指系統能夠適應不斷增長的負載需求,但同時要保證可接受的處理性能,一般分為兩大類:

    • 橫向(水平)擴展性。意味着通過向其中添加更多多的計算節點。
    • 縱向(垂直)擴展性。涉及系統單個節點中資源的添加或移除

    性能

    指系統在給定的計算資源內完成的工作量,完成的工作量和計算資源的比例(work/unit)越高,性能越高。

    計算資源的單位有以下幾種

    • 響應時間。一個函數或執行單元運行所需要的時間。
    • 延遲。某個系統被激活並提供響應所需的時間。
    • 吞吐量。系統處理信息的某種比率。

    可用性

    指系統處於完全可操作狀態的程度,以便在任何時候獲得調用請求時可以執行的能力

    • 可靠性
      系統的可用性和可靠性密切相關,系統越可靠,可用性就越高。
    • 故障恢復能力
      影響可用性的另一個因素是從故障中恢復的能力,包括了故障檢測、故障恢復、故障預防
    • 數據一致性
      CAP定理指出,系統的可用性與其數據一致性有密切聯繫。一致性和可用性一般膛會同時成立,因為可能通信失敗,系統可以在一致性或可用性之間進行選擇

    安全性

    避免被未經過身份驗證的訪問損害數據和邏輯,同時繼續向通過誰的其他系統和角色提供服務的一種能力。

    可部署性

    指軟件從開發環境到產品運行環境移交的難易程度。
    有以下相關因素:

    • 模塊結構。
      將系統劃分為易於部署的一個個子單元,則部署會容易
    • 產品運行環境與開發環境。與
      開發環境結構非常相似的產品運行環境會使部署
    • 開發生態系統支持。
      為系統提供成熟的工具鏈支持,允許各種依賴關係自動建立和驗證等配置項內容,從而提高可部署性。
    • 標準配置。
      一個好的方式是開發者保持開發環境的配置結構和產品運行環境一致。
    • 標準化基礎設施。
      將部署保持在一個標準化的基礎設施上,提高可部署性
    • 容器使用
      隨着Docker容器技術的普及,可以規範軟件,減少啟動/停止的開銷,從而使部署更容易。

    六、其他常見概念

    內聚

    一個模塊內相關聯程度的度量,描述的是模塊內的功能聯繫
    若一個模塊之間各元素聯繫緊密,則內聚性就高(高內聚)
    如果能做到將模塊做成一個功能類聚、獨立性強、內部緊密結合才是一個理想的類聚模塊,這對初學都來說,非常不容易,不光是個人技術能力的挑戰,更是對某個領域業務水平的挑戰。

    耦合

    各模塊間相互聯繫緊密程度的一種度量。
    模塊之間聯繫少,耦合性就越低,模塊之間的相對獨立性就越強。

    企業架構

    企業架構是一個定義企業結構和行為的概念藍圖。它確定了企業結構、流程、人員和信息流動如何與其核心目標相一致,以便有效地實現當前和未來的目標

    系統架構

    系統架構是系統的基本組織形式,由其結構和行為視圖表示。該結構由兩部分確定:構成系統的組件和組件的行為。組件的行為是指組件之間的交互,以及組件與外部系統之間的交互

    以上內容由chenqionghe整理,參考《軟件架構-Python語言實現》,light weight baby~

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    聚甘新

  • spring源碼分析——BeanPostProcessor接口

    spring源碼分析——BeanPostProcessor接口

     

      BeanPostProcessor是處理bean的後置接口,beanDefinitionMaps中的BeanDefinition實例化完成后,完成populateBean,屬性設置,完成

    初始化后,這個接口支持對bean做自定義的操作。

    一:BeanPostProcessor的使用

    定義一個測試用的model對象,name屬性默認為hello

    public class BeanDemo {
    
    	private String name = "hello";
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	@Override
    	public String toString() {
    		final StringBuffer sb = new StringBuffer("BeanDemo{");
    		sb.append("name='").append(name).append('\'');
    		sb.append('}');
    		return sb.toString();
    	}
    }
    

      

    自定義一個MyBeanPostProcessor類,實現BeanPostProcessor接口

    @Service
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		return null;
    	}
    
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if(beanName.equals("beanDemo")){
    			BeanDemo beanDemo = (BeanDemo)bean;
    			beanDemo.setName("kitty");
    			return beanDemo;
    		}
    		return bean;
    	}
    }
    

      

     

     

    從運行結果看,spring中維護的beanName為beanDemo的對象,name屬性為ketty

     

     

    二:看看源碼怎麼實現的

    1:實例化並且註冊到beanPostProcessors集合中

     

     

     

     

    主要的實例化邏輯在這個接口,這個接口的作用就是把所有實現BeanPostProcessor接口的類實例化,然後註冊到 beanPostProcessors這個緩存中

     

     

    	public static void registerBeanPostProcessors(
    			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    
    		// 獲取所有實現接口BeanPostProcessor的beanName
    		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    
    		// Register BeanPostProcessorChecker that logs an info message when
    		// a bean is created during BeanPostProcessor instantiation, i.e. when
    		// a bean is not eligible for getting processed by all BeanPostProcessors.
    		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    
    		// Separate between BeanPostProcessors that implement PriorityOrdered,
    		// Ordered, and the rest.
    		/**
    		 * 把實現PriorityOrdered 和 Ordered 和 其他的處理器分開
    		 */
    		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    		List<String> orderedPostProcessorNames = new ArrayList<>();
    		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    		/**
    		 * 1:遍歷集合postProcessorNames
    		 * 2:判斷類型,如果是PriorityOrdered,則實例化對象放入priorityOrderedPostProcessors集合,
    		 * Ordered 則放入orderedPostProcessorNames集合,其他的放入nonOrderedPostProcessorNames集合
     		 */
    		for (String ppName : postProcessorNames) {
    			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    				priorityOrderedPostProcessors.add(pp);
    				if (pp instanceof MergedBeanDefinitionPostProcessor) {
    					internalPostProcessors.add(pp);
    				}
    			}
    			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    				orderedPostProcessorNames.add(ppName);
    			}
    			else {
    				nonOrderedPostProcessorNames.add(ppName);
    			}
    		}
    
    		// First, register the BeanPostProcessors that implement PriorityOrdered.
    		// 首先對priorityOrderedPostProcessors集合中實例對象排序,然後註冊,放入beanFactory中緩存下來
    		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    
    		// Next, register the BeanPostProcessors that implement Ordered.
    		// 然後再實例化實現Ordered接口的對象,完成註冊
    		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    		for (String ppName : orderedPostProcessorNames) {
    			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    			orderedPostProcessors.add(pp);
    			if (pp instanceof MergedBeanDefinitionPostProcessor) {
    				internalPostProcessors.add(pp);
    			}
    		}
    		sortPostProcessors(orderedPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    
    		// Now, register all regular BeanPostProcessors.
    		// 最後實例化什麼都沒有實現的,完成實例化並註冊
    		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    		for (String ppName : nonOrderedPostProcessorNames) {
    			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    			nonOrderedPostProcessors.add(pp);
    			if (pp instanceof MergedBeanDefinitionPostProcessor) {
    				internalPostProcessors.add(pp);
    			}
    		}
    		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    
    		// Finally, re-register all internal BeanPostProcessors.
    		// 最後再次註冊內部postProcessor
    		sortPostProcessors(internalPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, internalPostProcessors);
    
    		// Re-register post-processor for detecting inner beans as ApplicationListeners,
    		// moving it to the end of the processor chain (for picking up proxies etc).
    		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    	}
    

      

     

     

    定義四類容器,高優先級有序、有序、無序、內部

     

     分類放入四種容器:

     

     

    註冊BeanPostProcessor,將實現BeanPostProcessor接口的對象放入beanPostProcessors緩存中

     

     

     

     

     

     

    註冊完PriorityOrdered的實現類后,再處理Ordered的實現類

     

     

    註冊什麼都沒有實現的BeanPostProcessor接口實現類,

     

     

    最後註冊內部的BeanPostProcessor對象

     

     到這裏BeanPostProcessor的實例化以及註冊工作完成,在beanFactory的beanPostProcessors集合中已經緩存了所有的beanPostProcessor的對象

     

    2:BeanPostProcessor的使用

    因為這個接口是bean的後置接口,所以需要bean創建並初始化完成,才可以發揮作用,上一步的緩存只是埋好點,以備使用,因為bean的實例化流程我們

    還沒有分析,這裏直接看一下怎麼使用的

     

     

    我們看一下init方法后的攔截,因為這個時候已經init完成,可以在後置接口中對bean做一下修改的操作

     

     

    調用到我們自定義的MyBeanPostProcessor實現類:

     

     

    把這個beanDemo對象屬性修改一下,修改完,再返回,將這個對象緩存到spring的一級緩存中。

     

     

    總結:

      BeanPostProcessor接口主要是對bean對象做一些自定義的操作,修改bean對象的信息,aop代理也是通過這種方式實現的,

    在refresh的registryBeanPostProcessor方法中實例化BeanPostProcessor對象,並且註冊到beanFactory容器的beanPostProcessors的緩存中,

    然後在後續的操作中攔截使用。

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司“嚨底家”!

    ※推薦評價好的iphone維修中心

    聚甘新

  • ASP.NET Core 對Controller進行單元測試

    單元測試對我們的代碼質量非常重要。很多同學都會對業務邏輯或者工具方法寫測試用例,但是往往忽略了對Controller層寫單元測試。我所在的公司沒見過一個對Controller寫過測試的。今天來演示下如果對Controller進行單元測試。以下內容默認您對單元測試有所了解,比如如何mock一個接口。在這裏多叨叨一句,面向接口的好處,除了能夠快速的替換實現類(其實大部分接口不會有多個實現),最大的好處就是可以進行mock,可以進行單元測試。

    測試Action

    下面的Action非常簡單,非常常見的一種代碼。根據用戶id去獲取用戶信息然後展示出來。下面看看如何對這個Action進行測試。

       public class UserController : Controller
        {
            private readonly IUserService _userService;
            public UserController(IUserService userService)
            {
                _userService = userService;
            }
    
            public IActionResult UserInfo(string userId)
            {
                if (string.IsNullOrEmpty(userId))
                {
                    throw new ArgumentNullException(nameof(userId));
                }
    
                var user = _userService.Get(userId);
                return View(user);
            }
          
        }
    

    測試代碼:

      [TestMethod()]
            public void UserInfoTest()
            {
    
                var userService = new Mock<IUserService>();
                userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User());
    
                var ctrl = new UserController(userService.Object);
                //對空參數進行assert
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo(null);
                });
                //對空參數進行assert
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo("");
                });
    
                var result = ctrl.UserInfo("1");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(ViewResult));
            }
    

    我們對一個Action進行測試主要的思路就是模擬各種入參,使測試代碼能夠到達所有的分支,並且Assert輸出是否為空,是否為指定的類型等。

    對ViewModel進行測試

    我們編寫Action的時候還會涉及ViewModel給視圖傳遞數據,這部分也需要進行測試。修改測試用例,加入對ViewModel的測試代碼:

      [TestMethod()]
            public void UserInfoTest()
            {
                var userService = new Mock<IUserService>();
                userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
                {
                    Id = "x"
                }) ;
    
                var ctrl = new UserController(userService.Object);
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo(null);
                });
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo("");
                });
    
                var result = ctrl.UserInfo("1");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(ViewResult));
                //對viewModel進行assert
                var vr = result as ViewResult;
                Assert.IsNotNull(vr.Model);
                Assert.IsInstanceOfType(vr.Model, typeof(User));
                var user = vr.Model as User;
                Assert.AreEqual("x", user.Id);
            }
    

    對ViewData進行測試

    我們編寫Action的時候還會涉及ViewData給視圖傳遞數據,這部分同樣需要測試。修改Action代碼,對ViewData進行賦值:

       public IActionResult UserInfo(string userId)
            {
                if (string.IsNullOrEmpty(userId))
                {
                    throw new ArgumentNullException(nameof(userId));
                }
    
                var user = _userService.Get(userId);
    
                ViewData["title"] = "user_info";
    
                return View(user);
            }
          
    

    修改測試用例,加入對ViewData的測試代碼:

       [TestMethod()]
            public void UserInfoTest()
            {
                var userService = new Mock<IUserService>();
                userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
                {
                    Id = "x"
                }) ;
    
                var ctrl = new UserController(userService.Object);
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo(null);
                });
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo("");
                });
    
                var result = ctrl.UserInfo("1");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(ViewResult));
    
                var vr = result as ViewResult;
                Assert.IsNotNull(vr.Model);
                Assert.IsInstanceOfType(vr.Model, typeof(User));
                var user = vr.Model as User;
                Assert.AreEqual("x", user.Id);
                //對viewData進行assert
                Assert.IsTrue(vr.ViewData.ContainsKey("title"));
                var title = vr.ViewData["title"];
                Assert.AreEqual("user_info", title);
            }
    

    對ViewBag進行測試

    因為ViewBag事實上是ViewData的dynamic類型的包裝,所以Action代碼不用改,可以直接對ViewBag進行測試:

         [TestMethod()]
            public void UserInfoTest()
            {
                var userService = new Mock<IUserService>();
                userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()
                {
                    Id = "x"
                }) ;
    
                var ctrl = new UserController(userService.Object);
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo(null);
                });
                Assert.ThrowsException<ArgumentNullException>(() => {
                    var result = ctrl.UserInfo("");
                });
    
                var result = ctrl.UserInfo("1");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(ViewResult));
    
                var vr = result as ViewResult;
                Assert.IsNotNull(vr.Model);
                Assert.IsInstanceOfType(vr.Model, typeof(User));
                var user = vr.Model as User;
                Assert.AreEqual("x", user.Id);
    
                Assert.IsTrue(vr.ViewData.ContainsKey("title"));
                var title = vr.ViewData["title"];
                Assert.AreEqual("user_info", title);
                //對viewBag進行assert
                string title1 = ctrl.ViewBag.title;
                Assert.AreEqual("user_info", title1);
            }
    

    設置HttpContext

    我們編寫Action的時候很多時候需要調用基類里的HttpContext,比如獲取Request對象,獲取Path,獲取Headers等等,所以有的時候需要自己實例化HttpContext以進行測試。

        var ctrl = new AccountController();
        ctrl.ControllerContext = new ControllerContext();
        ctrl.ControllerContext.HttpContext = new DefaultHttpContext();
    

    對HttpContext.SignInAsync進行mock

    我們使用ASP.NET Core框架進行登錄認證的時候,往往使用HttpContext.SignInAsync進行認證授權,所以單元測試的時候也需要進行mock。下面是一個典型的登錄Action,對密碼進行認證后調用SignInAsync在客戶端生成登錄憑證,否則跳到登錄失敗頁面。

       public async Task<IActionResult> Login(string password)
            {
                if (password == "123")
                {
                    var claims = new List<Claim>
                    {
                      new Claim("UserName","x")
                    };
                    var authProperties = new AuthenticationProperties
                    {
                    };
                    var claimsIdentity = new ClaimsIdentity(
                      claims, CookieAuthenticationDefaults.AuthenticationScheme);
                    await HttpContext.SignInAsync(
                        CookieAuthenticationDefaults.AuthenticationScheme,
                        new ClaimsPrincipal(claimsIdentity),
                        authProperties);
                    return Redirect("login_success");
                }
    
                return Redirect("login_fail");
            }
    

    HttpContext.SignInAsync其實個時擴展方法,SignInAsync其實最終是調用了IAuthenticationService里的SignInAsync方法。所以我們需要mock的就是IAuthenticationService接口,否者代碼走到HttpContext.SignInAsync會提示找不到IAuthenticationService的service。而IAuthenticationService本身是通過IServiceProvider注入到程序里的,所以同時需要mock接口IServiceProvider。

        [TestMethod()]
            public async Task LoginTest()
            {
                var ctrl = new AccountController();
    
                var authenticationService = new Mock<IAuthenticationService>();
                var sp = new Mock<IServiceProvider>();
                sp.Setup(s => s.GetService(typeof(IAuthenticationService)))
                    .Returns(() => {
                        return authenticationService.Object;
                    });
                ctrl.ControllerContext = new ControllerContext();
                ctrl.ControllerContext.HttpContext = new DefaultHttpContext();
                ctrl.ControllerContext.HttpContext.RequestServices = sp.Object;
    
               var result = await ctrl.Login("123");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(RedirectResult));
                var rr = result as RedirectResult;
                Assert.AreEqual("login_success", rr.Url);
    
                result = await ctrl.Login("1");
                Assert.IsNotNull(result);
                Assert.IsInstanceOfType(result, typeof(RedirectResult));
                rr = result as RedirectResult;
                Assert.AreEqual("login_fail", rr.Url);
            }
    

    對HttpContext.AuthenticateAsync進行mock

    HttpContext.AuthenticateAsync同樣比較常用。這個擴展方法同樣是在IAuthenticationService里,所以測試代碼跟上面的SignInAsync類似,只是需要對AuthenticateAsync繼續mock返回值success or fail。

         public async Task<IActionResult> Login()
            {
                if ((await HttpContext.AuthenticateAsync()).Succeeded)
                {
                    return Redirect("/home");
                }
    
                return Redirect("/login");
            }
    

    測試用例:

    
            [TestMethod()]
            public async Task LoginTest1()
            {
                var authenticationService = new Mock<IAuthenticationService>();
                //設置AuthenticateAsync為success
                authenticationService.Setup(s => s.AuthenticateAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
                    .ReturnsAsync(AuthenticateResult.Success(new AuthenticationTicket(new System.Security.Claims.ClaimsPrincipal(), "")));
                var sp = new Mock<IServiceProvider>();
                sp.Setup(s => s.GetService(typeof(IAuthenticationService)))
                    .Returns(() => {
                        return authenticationService.Object;
                    });
    
                var ctrl = new AccountController();
                ctrl.ControllerContext = new ControllerContext();
                ctrl.ControllerContext.HttpContext = new DefaultHttpContext();
                ctrl.ControllerContext.HttpContext.RequestServices = sp.Object;
    
                var act = await ctrl.Login();
                Assert.IsNotNull(act);
                Assert.IsInstanceOfType(act, typeof(RedirectResult));
                var rd = act as RedirectResult;
                Assert.AreEqual("/home", rd.Url);
                //設置AuthenticateAsync為fail
                authenticationService.Setup(s => s.AuthenticateAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
                   .ReturnsAsync(AuthenticateResult.Fail(""));
    
                act = await ctrl.Login();
                Assert.IsNotNull(act);
                Assert.IsInstanceOfType(act, typeof(RedirectResult));
                rd = act as RedirectResult;
                Assert.AreEqual("/login", rd.Url);
    
            }
    

    Filter進行測試

    我們寫Controller的時候往往需要配合很多Filter使用,所以Filter的測試也很重要。下面演示下如何對Fitler進行測試。

        public class MyFilter: ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                if (context.HttpContext.Request.Path.Value.Contains("/abc/"))
                {
                    context.Result = new ContentResult() {
                        Content = "拒絕訪問"
                    };
                }
    
                base.OnActionExecuting(context);
            }
        }
    

    對Filter的測試最主要的是模擬ActionExecutingContext參數,以及其中的HttpContext等,然後對預期進行Assert。

           [TestMethod()]
            public void OnActionExecutingTest()
            {
                var filter = new MyFilter();
                var actContext = new ActionContext(new DefaultHttpContext(),new RouteData(), new ActionDescriptor());
                actContext.HttpContext.Request.Path = "/abc/123";
                var listFilters = new List<IFilterMetadata>();
                var argDict = new Dictionary<string, object>();
                var actExContext = new ActionExecutingContext(
                    actContext ,
                    listFilters ,
                    argDict ,
                    new AccountController()
                    );
                 filter.OnActionExecuting(actExContext);
    
                Assert.IsNotNull(actExContext.Result);
                Assert.IsInstanceOfType(actExContext.Result, typeof(ContentResult));
                var cr = actExContext.Result as ContentResult;
                Assert.AreEqual("拒絕訪問", cr.Content);
    
                actContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
                actContext.HttpContext.Request.Path = "/1/123";
                listFilters = new List<IFilterMetadata>();
                argDict = new Dictionary<string, object>();
                actExContext = new ActionExecutingContext(
                    actContext,
                    listFilters,
                    argDict,
                    new AccountController()
                    );
                filter.OnActionExecuting(actExContext);
                Assert.IsNull(actExContext.Result);
            }
    

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

    ※教你寫出一流的銷售文案?

    ※超省錢租車方案

    聚甘新