南京金龍加碼純電動物流車 四款新品將在振威新能源汽車展亮相

近年來,在電子商務快速發展的強勢需求拉動下,中國電商物流繼續保持快速增長。在環境壓力較大的當下,物流行業推行新能源汽車也成了改善環境,治理霧霾的一個重要手段。

在新能源物流車形勢一片大好的情況下,新能源客車產品在細分市場銷量第二把交椅的南京金龍自然也不會錯過這一片藍海。據瞭解,南京金龍將於2017上海國際新能源汽車產業博覽會上推出四款新品純電動物流車。展會由振威展覽股份、中國土木工程學會城市公共交通學會、廣東省新能源汽車產業協會、廣東省充電設施協會及充電設施線上網聯合舉辦,將於2017年8月23-25日在上海新國際博覽中心舉行。

據瞭解,本次南京金龍四款純電動物流車型分別為開沃D07、開沃D09、開沃D10和開沃D11。此四款物流車涵蓋3.9-5.9米的中小型物流車,且秉承其一貫的強勁續航能力,滿載續航均在220-260公里,是名副其實的續航之王。其中開沃D07為微型純電動物流車,主要用於城市內的快遞派送。作為“最後一公里”快遞配送專家,其載貨空間達3.4立方米,載貨量可達600KG,完美滿足市網點到客戶的快遞配送。開沃D09、D10為輕型純電動物流車,載貨空間分別在6立方米和8立方米,載重分別為750kg和1000kg,主要用作城市間的物流配送“貨的”。

開沃D7純電動物流車

去年,南京金龍就推出了素有“快遞王”之稱的開沃E7,“物流王”開沃D11,早已以其380公里左右的高續航、1.55噸的高載重、12.3個立方的高容量等特點,4小時繞北京五環三圈贏得了新能源物流車界的良好口碑。D11作為城市大空間長續航的物流王更是經受市場考驗超過3年、以好品質得到客戶認可和擁護的車型,輕鬆勝任城市間的物流運輸。

3月1日,工信部官網正式公佈了《新能源汽車推廣應用推薦車型目錄(2017年第2批)》主要車型及參數。此次發佈的目錄涉及新能源乘用車、新能源客車及新能源專用車共有40家企業201款車型進入目錄。其中,南京金龍開沃牌NJL5040XXYBEV1純電動廂式運輸車入圍本次目錄。

資料顯示,2016年純電動物流車產量達5.78萬輛,且2017年剛開始,工信部就給電動物流車行業一個驚喜。首批新能源汽車推薦目錄發佈,以電動物流車為代表的專用車型共有36款,占總比19%。“新能源物流車正成為新能源商用車發展的一大亮點。”全國乘聯會秘書長崔東樹也指出,新能源物流車使用費用低,維(護)修簡單,從國家政策的扶持以及城市空氣污染的角度來看,新能源物流車急劇增長是必然的,也是長期的發展趨勢。

據不完全統計,北京、上海、廣東、天津等37省市出臺的新能源汽車政策裡都有提及純電動物流車的相關政策。隨著政策的明朗,行業逐漸趨於理性,純電動物流車市場迎來健康發展,其也將迎來真正的發展元年。業界普遍認為,2017年電動物流車行業預計將實現10萬輛左右的銷量,同比增速超過100%。

南京金龍市場負責人表示,本次展會的召開是一個很好的契機,南京金龍開沃純電動物流車憑藉靈活多變的空間及穩定的滿負荷續航里程,將極大地改變我國新能源物流車產業發展格局。未來,南京金龍憑藉產品技術優勢,不斷開拓物流、快遞行業需求,為全面實現“零排放物流”的行業大計而持續努力。

組委會聯繫方式:+86 20-83953286
連絡人:黃俊鵬
官方微信公眾號:nevechina

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

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

鋰電池原料暴漲,電動車產業受影響

鋰電池關鍵材料鈷、鋰價格暴漲,令電池乃至電動車製造商成本控制面臨極大壓力。

鈷的國際報價四月中旬來到每磅27.5美元,寫下八年新高記錄。從2017年初以來,鈷價累計漲幅達90%,對照一年之前,更是跳增2.5倍。根據主要交易機構官員表示,鈷的身價節節升高,主因需求看漲,市場預先囤貨所致。(日經新聞)

另外,鋰價近兩年翻升約三倍,電池製造商的成本上漲壓力可以想見,這將進一步轉嫁至電動車製造商身上。據估計,鈷約佔電池製造成本的兩成。

特斯拉大眾化電動車Model 3預計在今年稍晚量產,目前特斯拉已收到40萬輛預購訂單。除了特斯拉之外,日產新一代Leaf電動車也即將上市,這些均為鈷與鋰等電池材料提供炒作題材。

(本文內容由授權使用。圖片出處:wikipedia)

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

【其他文章推薦】

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

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

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

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

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

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

英威騰:高效電驅動專家 攜多款新品亮相振威新能源汽車展

中國已經成為全球新能源汽車發展最快,保有量最大的國家。但是隨著國家補貼的逐漸退坡,新能源汽車企業的壓力也越來越大。那麼隨著中國新能源汽車行業由政策導向變為市場導向,如何能快速、有效的降低生產成本,成為了新能源車企亟待解決的問題。

目前來說,動力電池方面價格在逐步的下降,除此之外電機、電控等環節也應該成為降低成本的重要方向。市場的規模效應一直都是降低成本的最好辦法,也就是說,除了動力電池之外,其餘的環節也需要這樣的規模效應。

英威騰作為電機控制器領域的龍頭企業,在新能源汽車電控產品的創新和研發上取得了重大的進展。據英威騰負責人介紹,後補貼時代的到來,英威騰將通過創新設計和規模效應來降低成本,通過提升產品品質降低費用,讓更多的客戶認可其產品品質和產品性能,從而推動大批量應用。這樣才會使企業減少對補貼的依賴,使產業更健康發展。

目前,英威騰電機控制器系列產品主要有純電動客車主電機控制器、混合動力客車主電機控制器、環衛車主電機控制器、物流車主電機控制器、輔助控制器及各種集成方案。其主電機控制器主要用於新能源汽車發電機與電動機的控制,可用來控制新能源汽車的非同步電機和永磁同步電機,實現高效、節能,控制器效率可達98%。輔助控制器主要用於新能源汽車轉向、刹車、上裝等的電機控制、蓄電池或輔助電源的供電等。

為了應對新能源汽車行業新的發展態勢,英威騰於去年8月成立了深圳市英威騰電動汽車充電技術有限公司,專門從事與電動汽車相關的電機控制器、電機、輔助控制器、 DC-DC轉換器、車載充電機、地面充電樁/充電機及電池組件產品和整體解決方案的開發及銷售。至此,英威騰基本形成了以電機電控、電池和充電設施等完善的新能源汽車配套產業解決方案產品體系。

據悉,英威騰將攜最新研發的電機控制器及其自主研發的最新充電設備產品首度亮相2017中國國際新能源汽車產業博覽會(以下簡稱振威新能源汽車展)。

本次英威騰將展出四款充電設備最新的相關產品。涵蓋了掛壁式充電樁,充電模組、充電機、DCDC。此四款產品的特點在於對電流的保護,特別是在過壓、欠壓、短路等方面表現出色。

振威新能源汽車展是由廣東省充電設施協會、廣東省新能源汽車產業協會、充電設施線上網及振威展覽股份聯合舉辦。將於2017年6月16-18日、2017年8月23-25日分別在深圳會展中心及上海新國際博覽中心舉行。超過800家新能源汽車產業相關的企業將參與本次展會,累積展示面積超過6萬平方米。

本次展會振威展覽股份醞釀了多年,從最初的鋰電展到充電設備展,經過多年的籌備,在2017年整合了新能源汽車產業的整車製造、核心三電(電池、電機、電控)、充電設備、BMS、零部件等全產業鏈環節,致力於打造中國新能源汽車產業第一展。

組委會聯繫方式:+86-20-83953286
連絡人:黃俊鵬
官方微信公眾號:nevechina

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

【其他文章推薦】

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

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

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

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

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

工研院高速充電鋁電池獲愛迪生獎,未來望應用電動車

台灣研發於國際發光!擁有「創新界奧斯卡獎」美譽的愛迪生獎(Edison Awards)於21日美國紐約公布得獎名單,工研院在經濟部能源局的支持下,以「可高速充放電鋁電池」贏得評審團青睞,勇奪「能源與永續」類的銀牌,這次獲獎讓台灣的創意與研發能力持續在國際舞台上大放光芒,也突顯工研院的技術創新領先國際。

愛迪生獎於1987 年設立,每年表彰全球創新產品與服務,紀念發明家愛迪生追求創意與卓越的精神,強調研發過程中的合作、試作、設計到產品應用開發,著重技術創新、差異化、商品化及影響力。歷屆獲獎者有iPad、3M 分子檢測系統、波音787 Dreamliner 等,今年入圍決選的國際大廠與研發機構包括:陶氏化學、MIT Media Lab、3M、美國國防部高等研究計劃署(DARPA)、Nokia、HP、默克藥廠等。

愛迪生獎資深遴選委員Steve Herring 在頒獎現場表示:「我們很榮幸2017 年愛迪生獎有工研院參賽,他們努力追求創新的精神正是我們想要表揚的。」愛迪生獎執行總監Frank Bonafilia 亦讚許工研院在電池技術上提供了前所未有的實質發展。

工研院綠能與環境研究所所長胡耀祖表示:「根據工研院產經中心(IEK)分析,2015 年全球商業電池市場約有791 億美元的規模。鋁電池突破過去30 年的技術瓶頸,不但可快速充放電,材料安全更不會引起爆炸,還可結合現有製程,大幅提升效率及降低成本,短期可望取代鉛酸電池,未來能將此應用擴大至電動機車、輕型電動車等交通載具,以及做為備用電力與儲能裝置。」

胡耀祖進一步指出:「鋁電池未來還可搭配再生能源,成為我國儲能的重要生力軍,開啟一個能源產業與應用的新時代。目前電池材料、組裝和終端應用等產業,都能切入未來鋁電池的廣大市場,可望帶動我國電池產業升級,迎接新能源產業商機。」

「可高速充放電鋁電池」為工研院與美國史丹佛大學共同合作,以地球上蘊藏豐富的石墨和鋁為原料,成功開發出全球第一個可以穩定充放電的鋁電池,只要一分鐘便可完成充電,且重複充放電逾萬次,仍可維持高蓄電量。此外,鋁電池所使用的離子液體在室溫下是液態的鹽類,若遇到高溫短路或是受到外力破壞,也不會爆炸燃燒。自2015 年登上英國《Nature》雜誌開始,「可高速充放電鋁電池」接連拿下2016 年百大研發獎(R&D 100 Awards)及2017 年愛迪生獎銀牌,在國際上備受肯定。工研院目前已布局包括核心電極材料、電解質材料、電芯與充電器等台灣及多國專利,且陸續獲證中,建立我國發展鋁電池產業的堅實根基。

(合作媒體:。圖片出處:TechNews)

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

【其他文章推薦】

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

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

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

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

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

Model3加速趕工略程序,冒日後召回維修風險

 

特斯拉(Tesla Inc)正在加速趕工,希望能在2017年9月讓平價電動車「Model 3」如期投產,但執行長馬斯克(Elon Musk)為了達標、在生產策略上背負不小風險,未來可能會面臨召回、維修等龐大成本。

路透社24日報導(),大多數的汽車製造商都會先訂購較便宜的原型設備來測試新車款的生產線,一旦成功打造出合適的車門、儀表板等零組件,就會把這些便宜的設備報廢。

然而,特斯拉在打造Model 3時卻跳過這項程序,直接訂購較為昂貴的永久設備加速趕工,目標就是趕上自己設定的9月量產期限。不過,用來量產數百萬輛汽車的設備假如無法順利製造出合適的零件,想要修正或直接替代,都得花費大把資金。特斯拉現有的車種產量雖少,卻已在品質方面出現問題,Model 3預設的年產量多達50萬台,一旦需要召回或進行保固期維修,都會拉高公司成本。

馬斯克3月份在一場法說會曾討論過這個問題。他當時說,利用「先進的分析技術」(即電腦模擬科技的代稱),就能幫助特斯拉直接進入安裝設備的階段。

的確,福斯(Volkswagen AG)旗下的奧迪(Audi)部門,已經領先業界在墨西哥新建廠房採用生產工具的電腦模擬科技,讓初步投產的時間,比一般流程快了30%。當時參與奧迪墨西哥廠投產流程的經理Peter Hochholdinger,如今已成為特斯拉生產部門的副總裁。除此之外,特斯拉在2015年收購一家密西根設備業者後,也學到更佳的設備修整技術,不但讓製造大型機具的速度加快30%、成本還能壓得更低。

話雖如此,特斯拉自2003年成立以來就面臨龐大的金融壓力,雖然3月的12億美元募資行動、以及將5%股權賣給騰訊(Tencent Holdings Ltd),讓公司喘了一口氣,但若是Model 3生產不順,後果堪慮。

CNET、路透社等多家外電報導,特斯拉甫於4月20日宣布在全球召回53,000輛Model S、Model X電動車,以便修正電子手煞車的問題。

特斯拉在聲明中表示,受到影響的是在2016年2月至10月期間生產的Model S與Model X,這些汽車的電子手煞車當中,有一款由第三方廠商供應的小型零組件因製造不當而容易裂開,會讓手煞車無法解除。

特斯拉強調,上述瑕疵至今並未引發任何車禍、也未導致人員死傷,估計這些車輛中,只有不到5%有問題,更換手煞車的時間僅需不到45分鐘。根據聲明,特斯拉正在跟義大利供應商Freni Brembo SpA合作,取得需要更替的零組件。

(本文內容由授權使用。圖片出處:Tesla)

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

【其他文章推薦】

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

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

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

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

Tesla擴大充電網絡規模,供卓越充電體驗

隨著Tesla 準備生產首款因應大眾市場的車型,Model S、Model X 的產量持續擴大,為客戶提供卓越的充電體驗成為Tesla 的首要目標。為現在和未來的車主提供便捷、豐富、可靠的充電服務對我們以及公司的使命至關重要。2017 年,Tesla 全球充電網絡規模將擴大一倍,並對現有的充電站進行擴建, 讓駕駛不必排隊等候充電;同時,我們還將擴大市中心區域的充電站 覆蓋。

一直以來,最便捷的充電方式都是夜間在停車位充電。為了更好的服務出門在外以及缺乏穩定家用充電設備的車主,我們將繼續大舉擴建Tesla 公共充電網絡。自2012 年Tesla 超級充電站網絡投入使用至今,Tesla 已經建造了5,400 多個超級充電座, 目的是讓全球20 多萬Tesla 車主都能方便地進行長途旅行。此外,我們還建立了一個已擁有9,000 多個目的地充電座的充電網絡,通過在酒店、度假村、餐廳等場所安裝Tesla 壁掛式充電座,為車主提供如同在家一般的便捷舒適的充電體驗。但我們知道, 要想真正推動電動車的普及,我們必須繼續投資建設充電基礎設施。

2017 年初,全球已經有5,000 多個Tesla 超級充電座;截至今年年底,Tesla 將把這個數量擴大一倍,超級充電座總數將突破1 萬個,目的地充電座總數增至約1.5 萬個。北美地區的超級充電座數量將增至現有的1.5 倍,僅加州就將增設超過1,000 個超級充電座。選址工作已經開始,新的充電站很快將投入建設,並於今年夏天旅行季節到來之前投入使用。

為此,我們將沿著最繁忙的行駛路線建設規模更大的充電站,這些道路沿線將同時出現數十座Tesla 超級充電站。此外,我們還將在距離公路較遠的地帶增設多個充電站,讓當地Tesla 駕駛可以隨需隨充,從而實現市中心隨處皆可充電的目標。

憑藉全球領先、便捷的充電技術,不斷打造獨一無二、充分利用此充電技術的電動車,Tesla 長期以來一直引領全球電動車產業的發展。充電網絡的不斷擴展將確保Tesla 駕駛在任何情況下都能快速、便捷地為車輛充電,而這正是Tesla 工作的首要目標。

針對台灣,目前已完成架構超過160 座目的地充電站,以及位於台北花博的6 座超級充電站。Tesla 預計於2017 年中完成超過200 座的目的地充電站,分佈於全台超過50 個地點。同時,車主高度期待位於中部、南部的超級充電站也預計同樣於年中完成建置。如此一來,Tesla 車主即可毫無顧慮的完成全島南北往返的長途旅行。針對如此的長途旅行,不僅是都會區,Tesla 也在各個熱門景點附近的飯店設立目的地充電站,以便車主旅途中隔夜充電使用。

(合作媒體:。圖片出處:Steve Jurvetson via Flickr CC2.0)  

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

【其他文章推薦】

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

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

※超省錢租車方案

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

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

編碼的道與禪

該文章發布在github中,如果您覺得寫的還不錯的話,可以 star 一下進行支持,傳送門:TechShare。

Bob 大叔在《代碼整潔之道》一書的前言打趣着說,當你寫的代碼在經受代碼審查時,如果審查者憤怒的吼道“What the fuck is this shit?”等言辭激烈的詞語時,那說明你寫的是 Bad Code;如果審查者只是漫不經心的吐出幾個“What the fuck?”,那說明你寫的是 Good Code。這就是衡量代碼質量的唯一標準——每分鐘罵出“What the fuck?”的頻率。

想寫出整潔的代碼很難,有一部分原因在於糟糕的代碼太容易編寫。想快點完成任務時,考慮不周全時,忽略安全時,隨意命名時,參數過多時,嵌套太深時,未及時更改註釋時,違反法則時,重複你自己時等等情形,我們有太多的機會來製造糟糕的代碼。只有嚴肅對待自己的代碼,了解哪些事情會使我們的代碼變味,才有可能寫出整潔的代碼。

寫代碼和寫文章在某種程度上有相似之處,好的文章一定有好的可讀性,寫代碼也一樣,只有優美乾淨的代碼才能具有良好的可讀性。編寫具有可讀性的代碼不光是保持有意義的命名就行,如果你想成為一名更好的程序員,寫代碼時你需要注意的有很多,比如:

  1. 規範本地變量的位置
  2. 使函數盡量短小
  3. 調用者盡可能放在被調用者上面
  4. 保持代碼擁有良好的格式
  5. 編寫只做一件事的函數
  6. 函數參數不要超過三個
  7. 暴露時序耦合
  8. 使用異常代替返回錯誤碼

除此之外,你還須牢記眾多設計原則,如:

  1. 開放封閉原則(OCP)
  2. 迪米特法則
  3. 依賴倒置原則(DIP)
  4. 單一職責原則(SRP)
  5. 里氏替換原則(LSP)
  6. 不要重複(DRY)
  7. 你不會需要它(YAGNI)

當然僅有這些是不夠的,這不是騎自行車,學寫整潔代碼得花許多功夫,必須不斷實踐,從失敗中提取代碼的壞味道並從中得到啟發。

編寫整潔代碼,你需要牢記並遵守很多東西,但這並不是循規蹈矩和刻板,而是對簡單之美、代碼之美的追求。代碼整潔之道,是編寫優秀代碼的一種方法,其核心是儘力使代碼保持簡單——Keep It Simple, Stupid。判斷一個人寫的代碼的好壞,不是看它的代碼寫的有多複雜,而是看他有沒有把複雜的事物抽象出來並用簡單的方式去描述它,此外這個人對代碼的態度也至關重要,大多數時候我們並不能從一開始就把代碼寫的很完美,當我們需要快速做出一個原型,或者一開始代碼看起來不錯,但新的需求使現有的設計無法滿足,如果不對設計進行改動的話,那麼代碼就會變的醜陋,如果你熱愛自己正在做的事情,崇尚代碼之美,那麼你就會有足夠的動力去重構它、完善它,而不是破壞結構使代碼腐爛。

保持簡單、追求簡單,我想這就是編碼之中的禪意,一種追求本真的境界。這種禪在 Python 的設計哲學中體現的淋漓盡致,讓我們在 Python 解釋器中輸入“import this”,來看看經典的 Python 之禪。

  • Beautiful is better than ugly.
    優美勝於醜陋。
  • Explicit is better than implicit.
    顯式勝於隱式。
  • Simple is better than complex.
    簡單勝於複雜。
  • Complex is better than complicated.
    複雜勝於難懂。
  • Flat is better than nested.
    扁平勝於嵌套。
  • Sparse is better than dense.
    分散勝於密集。
  • Readability counts.
    可讀性應當被重視。
  • Special cases aren’t special enough to break the rules. Although practicality beats purity.
    儘管實用性會打敗純粹性,特例也不能凌駕於規則之上。
  • Errors should never pass silently. Unless explicitly silenced.
    除非明確地使其沉默,錯誤永遠不應該默默地溜走。
  • In the face of ambiguity, refuse the temptation to guess.
    面對不明確的定義,拒絕猜測的誘惑。
  • There should be one– and preferably only one –obvious way to do it.
    用一種方法,最好只有一種方法來做一件事。
  • Although that way way not be obvious at first unless you’re Dutch.
    雖然一開始這種方法並不是顯而易見的,但誰叫你不是Python之父呢。
  • Now is better than never. Although never is often better than right now.
    做比不做好,但立馬去做有時還不如不做。
  • If the implementation is hard to explain, it’s a bad idea.
    如果實現很難說明,那它是個壞想法。
  • If the implementation is easy to explain, it may be a good idea.
    如果實現容易解釋,那它有可能是個好想法。
  • Namespaces are one honking great idea – let’s do more of those!
    命名空間是個絕妙的想法,讓我們多多地使用它們吧!

道着重於方法,禪着重於態度,讓我們把這兩者相結合,做一個有追求的程序員,為成為軟件匠人而奮鬥吧。

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

【其他文章推薦】

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

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

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

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

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

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

看了Java的Class的源碼,我自閉了

java源碼之Class

​ 源碼的重要性不言而喻,雖然枯燥,但是也有拍案叫絕。這是我的源碼系列第二彈,後續還會一直更新,歡迎交流。String源碼可以看我的Java源碼之String,如有不足,希望指正。

1.class這個類是什麼

Class的本質也是一個類,只不過它是將我們定義類的共同的部分進行抽象,比如我們常定義的類都含有構造方法,類變量,函數,而Class這個類就是來操作這些屬性和方法的。當然我們常定義的類包含的類型都可以通過Class間接的來操作。而類的類型包含一般的類,接口,枚舉類型,註解類型等等。這麼說可能有點太理論,我們看下面這個例子:

我們將生活中的一類事物抽象為一個類的時候,往往是因為他們具有相同的共性和不同的個性。定義一個類的作用就是將相同的共性抽離出來。一般的類都包含屬性和方法(行為),下面我們定義水果和汽車這兩個大類:

代碼如下:

汽車類:

class Car{

    // 定義屬性
    private String name;
    private String color;

    /**
     * 定義兩個構造方法
     */
    public Car(){

    }

    public Car(String name,String color){
        this.name = name;
        this.color = color;
    }

    /**
     * 定義兩個普通方法(行為)
     */
    public void use(){
        
    }
    
    public void run(){
        
    }

    /**
     * 屬性的get和set方法
     * @return
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
         this.color = color;
    }
}


水果類:

class Fruit{

    // 定義屬性
    private String name;
    private int size;

    /**
     * 定義兩個構造方法
     */
    public Fruit(){

    }

    public Fruit(String name,int size){
        this.name = name;
        this.size =size;
    }

    /**
     * 定義兩個方法(行為)
     */
    public void use(){
        
    }
    
    public void doFruit(){
        
    }

    /**
     * 屬性的get和set方法
     * @return
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }
}

可以看到水果和汽車這兩個類都有共同的部分,也就是一個類共同的部分,那就是屬性和方法,而Class就是來操作我們定義類的屬性和方法。

​小試牛刀:通過Class這個類來獲取Fruit這個類中定義的方法;

public static void main(String[] args) {

        Fruit fruit = new Fruit();
        Class fruitClass = fruit.getClass();

        Method[] fruitMethods = fruitClass.getMethods();
        System.out.println("方法個數:" + fruitMethods.length);

        for (Method method : fruitMethods) {
            //得到返回類型
            System.out.print("方法名稱和參數:" + method.getName() + "(");
            //取得某個方法對應的參數類型數組
            Class[] paramsType = method.getParameterTypes();
            for (Class paramType : paramsType) {
                System.out.print(paramType.getTypeName() + " ");
            }
            System.out.print(")");

            Class returnType = method.getReturnType();
            System.out.println("返回類型:" + returnType.getTypeName());
        }
    }

運行結果:

方法個數:15
方法名稱和參數:getName()返回類型:java.lang.String
方法名稱和參數:setName(java.lang.String )返回類型:void
方法名稱和參數:getSize()返回類型:int
方法名稱和參數:setSize(int )返回類型:void
方法名稱和參數:use()返回類型:void
方法名稱和參數:doFruit()返回類型:void
方法名稱和參數:wait()返回類型:void
方法名稱和參數:wait(long int )返回類型:void
方法名稱和參數:wait(long )返回類型:void
方法名稱和參數:equals(java.lang.Object )返回類型:boolean
方法名稱和參數:toString()返回類型:java.lang.String
方法名稱和參數:hashCode()返回類型:int
方法名稱和參數:getClass()返回類型:java.lang.Class
方法名稱和參數:notify()返回類型:void
方法名稱和參數:notifyAll()返回類型:void

這裏可能有人疑惑了,Fruit類並沒有定義的方法為什麼會出現,如wait(),equals()方法等。這裏就有必要說一下java的繼承和反射機制。在繼承時,java規定每個類默認繼承Object這個類,上述這些並沒有在Fruit中定義的方法,都是Object中的方法,我們看一下Object這個類的源碼就會一清二楚:

 public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

 public final native void wait(long timeout) throws InterruptedException;

 public final void wait() throws InterruptedException {
        wait(0);
    }

而Class類中的getMethods()方法默認會獲取父類中的公有方法,也就是public修飾的方法。所以Object中的公共方法也出現了。

注: 要想獲得父類的所有方法(public、protected、default、private),可以使用apache commons包下的FieldUtils.getAllFields()可以獲取類和父類的所有(public、protected、default、private)屬性。

是不是感覺非常的強大 ,當然,使用Class來獲取一些類的方法和屬性的核心思想就是利用了Java反射特性。萬物皆反射,可見反射的強大之處,至於反射的原理,期待我的下一個博客。

2.常用方法的使用以及源碼分析

2.1構造方法

源碼如下:

 private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }

可以看到Class類只有一個構造函數,並且是私有的。也就是說不能通過new來創建這個類的實例。官方文檔的解釋:私有構造函數,僅Java虛擬機創建Class對象。我想可能就是為了安全,具體原因不是很了解。如果有了解的話,可以在評論區內共同的交流。

Class是怎麼獲取一個實例的。

那麼既然這個class構造器私有化,那我們該如何去構造一個class實例呢,一般採用下面三種方式:

1.運用.class的方式來獲取Class實例。對於基本數據類型的封裝類,還可以採用.TYPE來獲取相對應的基本數據類型的Class實例,如下的示例。

 // 普通類獲取Class的實例。接口,枚舉,註解,都可以通過這樣的方式進行獲得Class實例
Class fruitClass = Fruit.class;

// 基本類型和封裝類型獲得Class實例的方式,兩者等效的
Class intClass = int.class;
Class intClass1 = Integer.TYPE;

下面的表格兩邊等價:

boolean.class Boolean.TYPE
char.class Character.TYPE
byte.class Byte.TYPE
short.class Short.TYPE
int.class Integer.TYPE
long.class Long.TYPE
float.class Float.TYPE
double.class Double.TYPE
void.class Void.TYPE

但是這種方式有一個不足就是對於未知的類,或者說不可見的類是不能獲取到其Class對象的。

2.利用對象.getClass()方法獲取該對象的Class實例;

這是利用了Object提供的一個方法getClass() 來獲取當著實例的Class對象,這種方式是開發中用的最多的方式,同樣,它也不能獲取到未知的類,比如說某個接口的實現類的Class對象。

Object類中的getClass()的源碼如下:

public final native Class<?> getClass();

源碼說明:

可以看到,這是一個native方法(一個Native Method就是一個java調用非java代碼的接口),並且不允許子類重寫,所以理論上所有類型的實例都具有同一個 getClass 方法。

使用:

 Fruit fruit = new Fruit();
 Class fruitClass = fruit.getClass();

3.使用Class類的靜態方法forName(),用類的名字獲取一個Class實例(static Class forName(String className) ),這種方式靈活性最高,根據類的字符串全名即可獲取Class實例,可以動態加載類,框架設計經常用到;

源碼如下:

    /*
     由於方法區 Class 類型信息由類加載器和類全限定名唯一確定,所以參數name必須是全限定名,
     參數說明   name:class名,initialize是否加載static塊,loader 類加載器
     */
    public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        Class<?> caller = null;
        
        // 1.進行安全檢查
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
           ....
            }
        }
        // 2.調用本地的方法
        return forName0(name, initialize, loader, caller);
    }
   
    // 3.核心的方法
    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
      throws ClassNotFoundException;

   /* 
    這個 forName是上述方法的重載,平時一般都使用這個 方法默認使用調用者的類加載器,將類的.class文件加載     到 jvm中
    這裏傳入的initialize為true,會去執行類中的static塊
    */
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

源碼說明已在註釋中說明,有些人會疑惑, static native Class<?> forName0()這個方法的實現。

這就要說到java的不完美的地方了,Java的不足除了體現在運行速度上要比傳統的C++慢許多之外,Java無法直接訪問到操作系統底層(如系統硬件等),為此Java使用native方法來擴展Java程序的功能。有關native的方法請移步這裏。

基本使用:

 Class fruitClass = Class.forName("cn.chen.test.util.lang.Fruit");

: 這種方式必須使用類的全限定名,,這是因為由於方法區 Class 類型信息由類加載器和類全限定名唯一確定,否則會拋出ClassNotFoundException的異常。

2.2一般方法以及源碼分析:

Class類的一般的方法總共有六十多種,其實看到這麼多方法咱也不要慫,這裏面還有很多重載的方法,根據二八原則,我們平時用的也就那麼幾個方法,所以這裏只對以下幾個方法的使用和實現進行交流,其他的方法可以移步Java官方文檔:

2.2.1 獲得類的構造方法

這個方法主要是用來了解一個類的構造方法有哪些,包含那些參數,特別是在單例的模式下。一般包含的方法如下:

  • public Constructor[] getConstructors() :獲取類對象的所有可見的構造函數

  • public Constructor[] getDeclaredConstructors():獲取類對象的所有的構造函數

  • public Constructor getConstructor(Class… parameterTypes): 獲取指定的可見的構造函數,參數為:指定構造函數的參數類型數組,如果該構造函數不可見或不存在,會拋出 NoSuchMethodException 異常

  • public Constructor getDeclaredConstructor(Class… parameterTypes) :獲取指定的構造函數,參數為:指定構造函數的參數類型數組,無論構造函數可見性如何,均可獲取

基本使用:

Constructor[] constructors = fruitClass.getConstructors();
 for (Constructor constructor : constructors) {
            System.out.println("獲得共有的構造方法:"+constructor);
        }

輸出結果:

獲得共有的構造方法:public cn.chen.test.util.lang.Fruit()
獲得共有的構造方法:public cn.chen.test.util.lang.Fruit(java.lang.String,int)

可以看到我們前面定義的來個構造方法,都被打印出來了。注意getConstructors()只能獲得被public修飾的構造方法,如果要獲得被(protected,default,private)修飾的構造方法,就要使用的getDeclaredConstructors()這個方法了。接下來,修改Fruit中的一個構造方法為private:

 private  Fruit(String name,int size){
        this.name = name;
        this.size =size;
    }

使用getConstructors()和getDeclaredConstructors()着兩個方法進行測試:

       Class fruitClass = Fruit.class;       
       Constructor[] constructors = fruitClass.getConstructors();
       Constructor[] constructors1 = fruitClass.getDeclaredConstructors();

        for (Constructor constructor : constructors) {
            System.out.println("獲得共有的構造方法:"+constructor);
        }

        System.out.println("=================================================");
        for (Constructor constructor : constructors1) {
            System.out.println("獲得所有的構造方法:"+constructor);
        }

輸出結果:

獲得共有的構造方法:public cn.chen.test.util.lang.Fruit()
===================分隔線=============================
獲得所有的構造方法:public cn.chen.test.util.lang.Fruit()
獲得所有的構造方法:private cn.chen.test.util.lang.Fruit(java.lang.String,int)

可以看到兩者的區別。所以,反射在一定程度上破壞了java的封裝特性。畢竟人無完人,語言亦是一樣。

getConstructors()的源碼分析:

public Constructor<?>[] getConstructors() throws SecurityException {
          
        // 1.檢查是否允許訪問。如果訪問被拒絕,則拋出SecurityException。
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        return copyConstructors(privateGetDeclaredConstructors(true));
    }
    
 private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) {
      // 2.使用克隆,得到當前類的所有構造函數   
      Constructor<U>[] out = arg.clone();
     // 3.使用ReflectionFactory構造一個對象,也是不使用構造方法構造對象的一種方式。
        ReflectionFactory fact = getReflectionFactory();
     // 4.遍歷,將構造函數進行拷貝返回,注意在調用fact.copyConstructor(out[i])這個方法的時候,還會進行安全檢查,用的就是下面的LangReflectAccess() 這個方法。
        for (int i = 0; i < out.length; i++) {
            out[i] = fact.copyConstructor(out[i]);
        }
        return out;
    }



 private static LangReflectAccess langReflectAccess() {
        if (langReflectAccess == null) {
            Modifier.isPublic(1);
        }

        return langReflectAccess;
    } 

通過打斷點調試,可以看到下面的信息:

代碼的調用邏輯在註釋里已進行說明。

2.2.2 獲得屬性

主要獲取類的屬性字段,了解這個類聲明了那些字段。

一般有四個方法:

  • public Field[] getFields():獲取所有可見的字段信息,Field數組為類中聲明的每一個字段保存一個Field 實例
  • public Field[] getDeclaredFields():獲取所有的字段信息
  • public Field getField(String name) :通過字段名稱獲取字符信息,該字段必須可見,否則拋出異常
  • public Field getDeclaredField(String name) :通過字段名稱獲取可見的字符信息

基本使用:

首先我們在Fruit的類中加入一個public修飾的屬性:

    public double weight;
Class fruitClass = Fruit.class; 
Field[] field2 = fruitClass.getFields();
        for (Field field : field2) {
            System.out.println("定義的公有屬性:"+field);
        }

        Field[] fields = fruitClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("定義的所有屬性:"+field);
        }

輸出結果:

定義的公有屬性:public double cn.chen.test.util.lang.Fruit.weight
========================分隔線============================
定義的所有屬性:private java.lang.String cn.chen.test.util.lang.Fruit.name
定義的所有屬性:private int cn.chen.test.util.lang.Fruit.size
定義的所有屬性:public double cn.chen.test.util.lang.Fruit.weight

源碼分析,就以getFileds()這個方法為例,涉及以下幾個方法:

public Field[] getFields() throws SecurityException {
        // 1.檢查是否允許訪問。如果訪問被拒絕,則拋出SecurityException。
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        return copyFields(privateGetPublicFields(null));
    }
 
 private static Field[] copyFields(Field[] arg) {
         // 2. 聲明一個Filed的數組,用來存儲類的字段 
        Field[] out = new Field[arg.length];
        //  3.使用ReflectionFactory構造一個對象,也是不使用構造方法構造對象的一種方式。
        ReflectionFactory fact = getReflectionFactory();
       // 4.遍歷,將字段複製后返回。
        for (int i = 0; i < arg.length; i++) {
            out[i] = fact.copyField(arg[i]);
        }
        return out;
    }
    
 public Field copyField(Field var1) {
        return langReflectAccess().copyField(var1);
    }
 
// 再次檢查屬性的訪問權限
  private static LangReflectAccess langReflectAccess() {
        if (langReflectAccess == null) {
            Modifier.isPublic(1);
        }

        return langReflectAccess;
    }

2.2.3 獲得一般方法

就是獲取一個類中的方法,一般有以下幾個方法:

  • public Method[] getMethods(): 獲取所有可見的方法

  • public Method[] getDeclaredMethods() :獲取所有的方法,無論是否可見

  • public Method getMethod(String name, Class… parameterTypes)

    參數說明:

  1. 通過方法名稱、參數類型獲取方法
  2. 如果你想訪問的方法不可見,會拋出異常
  3. 如果你想訪問的方法沒有參數,傳遞 null作為參數類型數組,或者不傳值)
  • public Method getDeclaredMethod(String name, Class… parameterTypes)
  1. 通過方法名稱、參數類型獲取方法
  2. 如果你想訪問的方法沒有參數,傳遞 null作為參數類型數組,或者不傳值)

基本使用:

//在fruit中定義一個這樣的方法
 private  void eat(String describe){
        System.out.println("通過getMethod()方法調用了eat()方法:  "+describe);
    }

調用這個方法:

        Class fruitClass = Fruit.class;
        Method method = fruitClass.getDeclaredMethod("eat",String.class);
        method.setAccessible(true);
        method.invoke(fruitClass.newInstance(),"我是該方法的參數值");

輸出結果:

  通過getMethod()方法調用了eat()方法:我是該方法的參數值

分析getDeclaredMethod()涉及的源碼:

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        // 1.檢查方法的修飾符
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        // 2.searchMethods()方法的第一個參數確定這個方法是不是私有方法,第二個參數我們定義的方法名,第三個參數就是傳入的方法的參數類型
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        return method;
    }

// 這個方法就是通過傳入的方法名找到我們定義的方法,然後使用了Method的copy()方法返回一個Method的實例,我們通過操作mehtod這個實例就可以操作我們定義的方法。
 private static Method searchMethods(Method[] methods,
                                        String name,
                                        Class<?>[] parameterTypes)
    {
        Method res = null;
        String internedName = name.intern();
        for (int i = 0; i < methods.length; i++) {
            Method m = methods[i];
            if (m.getName() == internedName
                && arrayContentsEq(parameterTypes, m.getParameterTypes())
                && (res == null
                    || res.getReturnType().isAssignableFrom(m.getReturnType())))
                res = m;
        }

        return (res == null ? res : getReflectionFactory().copyMethod(res));
    }

 public Method copyMethod(Method var1) {
        return langReflectAccess().copyMethod(var1);
    }

 
// 檢查屬性的訪問權限
  private static LangReflectAccess langReflectAccess() {
        if (langReflectAccess == null) {
            Modifier.isPublic(1);
        }

        return langReflectAccess;
    }

2.2.4 判斷類的類型的方法

這類型的方法顧名思義,就是來判斷這個類是什麼類型,是接口,註解,枚舉,還是一般的類等等。部分方法如下錶

boolean isAnnotation()判斷是不是註解
boolean isArray() 判斷是否為數組
boolean isEnum()判斷是否為枚舉類型
boolean isInterface() 是否為接口類型
boolean isMemberClass()當且僅當基礎類是成員類時,返回“true”
boolean isPrimitive()確定指定的“類”對象是否表示原始類型。
boolean isSynthetic()如果這個類是合成類,則返回’ true ‘;否則返回“false”。

基本用法:

// 定義一個接口:
interface  Animal{
    public void run();
}

判斷是不是一個接口:

Class AnimalClass = Animal.class;
 boolean flag = AnimalClass.isInterface();
 System.out.println(flag);

輸出結果:

true

源碼分析isInterface():

 public native boolean isInterface();

這是一個native方法,大家都知道native方法是非Java語言實現的代碼,供Java程序調用的,因為Java程序是運行在JVM虛擬機上面的,要想訪問到比較底層的與操作系統相關的就沒辦法了,只能由靠近操作系統的語言來實現。

2.2.5 toString()方法

將對象轉換為字符串。字符串表示形式是字符串“類”或“接口”,後跟一個空格,然後是該類的全限定名。

基本使用:

// 這是前面定義的兩個類Fruit和Car,Car是一個接口
 Class fruitClass = Fruit.class;
 Class AnimalClass = Animal.class;
 System.out.println(AnimalClass.toString());
 System.out.println(fruitClass.toString());

輸出結果:

// 格式  字符串“類”或“接口”,後跟一個空格,然後是該類的全限定名
interface cn.chen.test.util.lang.Animal
class cn.chen.test.util.lang.Fruit

源碼如下:

 public String toString() {
       // 先是判斷是接口或者類,然後調用getName輸出類的全限定名
        return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
            + getName();
    }

  public native boolean isInterface();
  public native boolean isPrimitive();

追本溯源,方能闊步前行。

參考資料

​ https://blog.csdn.net/x_panda/article/details/17120479

​ https://juejin.im/post/5d4450fbe51d4561ce5a1be1

​ JavaSE的官方文檔

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

【其他文章推薦】

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

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

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

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

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

Java Jar 包加密 — XJar

Java Jar 包加密

一、緣由

  Java的 Jar包中的.class文件可以通過反彙編得到源碼。這樣一款應用的安全性就很難得到保證,別人只要得到你的應用,不需花費什麼力氣,就可以得到源碼。

  這時候就需要對jar進行加密處理。

二、技術&工具

  XJar

  GitHub:https://github.com/core-lib/xjar

  碼雲:https://gitee.com/core-lib/xjar?_from=gitee_search

  maven集成 XJar

 

  GitHub:https://github.com/core-lib/xjar-maven-plugin

  碼雲:https://gitee.com/core-lib/xjar-maven-plugin?_from=gitee_search

  xjar-agent-hibernate

  GitHub:https://github.com/core-lib/xjar-agent-hibernate

  碼雲:https://gitee.com/core-lib/xjar-agent-hibernate?_from=gitee_search

  go語言、maven、eclipse

  文檔可以到github、碼雲上去了解,這裏只描述使用過程,親測可用!

三、實現過程

  這裏使用的maven版本是:apache-maven-3.6.3,低版本的沒測試過

  1、XJar

   1-1.在github或碼雲上下載該項目,導入eclipse,然後新建一個main類,填入參數,直接運行得到一個xjar.go 和 加密后的jar包【xx-encrypted.jar】。

    注意:這種直接在項目中跑mian,不提倡,會導致jar包中包含這段代碼,導緻密碼泄露,所以要通過命令行的方式來執行這段代碼。

    

    1-2.這時候可以用反編譯軟件 jb-gui 打開jar看看加密的效果,這時候反編譯軟件已經看不到.class文件的源碼了

 

 

     1-3.加密后的jar包,不能直接用原來的java 命令來執行,需要用到同時生成的xjar.go文件,執行命令 go build xjar.go

      這裏要等待一小會,等待編譯出目標文件xjar.exe

      

 

 

       

      1-4. 最後執行命令,xjar java -jar /path/to/encrypted.jar,即可運行加密后的jar包

       注意:Spring Boot + JPA(Hibernate) 啟動會報錯

                   1-5:沒有採用 Spring Boot + JPA(Hibernate) 技術的可以略過以下步驟。

      a、到碼雲、GitHub上下載  xjar-agent-hibernate  項目

      b、導入eclipse 打包出jar包

      c、然後執行命令  xjar java -javaagent:xjar-agent-hibernate-v1.0.0.jar -jar path\wx-encrypted.jar,即可正常運行

      

   2、maven集成 XJar

    第二種方式就比較簡單了,直接在項目中引入xjar-maven-plugin,然後打包就可以了,其他操作方式和第一種類似

    注意:密碼最好採用命令行方式

<pluginRepositories>
  <pluginRepository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
  </pluginRepository>
</pluginRepositories>

       

 <plugin> <groupId>com.github.core-lib</groupId> <artifactId>xjar-maven-plugin</artifactId> <version>4.0.0</version> <executions> <execution> <goals> <goal>build</goal> </goals> <phase>install</phase> <configuration> <password>1233445</password> <includes>
                   <!----> <include>/com/xxx/xxx/**/*.class</include> </includes> <!-- 無需加密的資源路徑表達式 --> <excludes> <exclude>static/**</exclude> <exclude>META-INF/resources/**</exclude> </excludes> <!-- 源jar所在目錄 --> <sourceDir>path\</sourceDir> <!-- 源jar名稱 --> <sourceJar>xxx.jar</sourceJar> <!-- 目標jar存放目錄 --> <targetDir>path\test2</targetDir> <!-- 目標jar名稱 --> <targetJar>xxx-encrypted.jar</targetJar> </configuration> </execution> </executions> </plugin>

四、後記

  其實所有軟件,都可以被破解,只是破解過程是簡單還是複雜、以及破解成本的高低。

  最關鍵的還是自己軟件要更新迭代的快,這樣才能把模仿者遠遠甩在身後。

  轉發請註明出處!!!

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

【其他文章推薦】

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

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

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

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

程序員必須掌握的Java 框架,小白學會之後15k不是問題

Spring 的核心特性是什麼?Spring 優點?

Spring 的核心是控制反轉(IoC)和面向切面(AOP)

Spring 優點:

程序員必須掌握的Java 框架,學會之後50k不是問題
(1)方便解耦,簡化開發 (高內聚低耦合)

Spring 就是一個大工廠(容器),可以將所有對象創建和依賴關係維護,交給 Spring管理

spring 工廠是用於生成 bean

(2)AOP 編程的支持

Spring 提供面向切面編程,可以方便的實現對程序進行權限攔截、運行監控等功能

(3) 聲明式事務的支持

只需要通過配置就可以完成對事務的管理,而無需手動編程

(4) 方便程序的測試

Spring 對 Junit4 支持,可以通過註解方便的測試 Spring 程序

(5)方便集成各種優秀框架

Spring 不排斥各種優秀的開源框架,其內部提供了對各種優秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持

(6) 降低 JavaEE API 的使用難度

Spring 對 JavaEE 開發中非常難用的一些 API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些 API 應用難度大大降低

spring 框架中需要引用哪些 jar 包,以及這些 jar 包的用途

4 + 1 : 4 個 核 心 ( beans 、 core 、 context 、 expression ) + 1 個 依 賴(commons-loggins…jar)

理解 AOP、IoC 的基本原理;

IOC:控制反轉(IoC)與依賴注入(DI)是同一個概念,

控制反轉的思想:

傳統的 java 開發模式中,當需要一個對象時,我們會自己使用 new 或者getInstance 等直接或者間接調用構造方法創建一個對象。而在 spring 開發模式中,spring 容器使用了工廠模式為我們創建了所需要的對象,不需要我們自己創建了,直接調用 spring 提供的對象就可以了

引入 IOC 的目的:

(1)脫開、降低類之間的耦合;(2)倡導面向接口編程、實施依賴倒換原則;

(3)提高系統可插入、可測試、可修改等特性

AOP:面向切面編程(AOP)面向切面編程思想:

在面向對象編程(oop)思想中,我們將事物縱向抽成一個個的對象。而在面向切面編程中,我們將一個個的對象某些類似的方面橫向抽成一個切面,對這個切面進行一些如權限控制、事物管理,記錄日誌等公用操作處理的過程。

切面:簡單說就是那些與業務無關,卻為業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊之間的耦合度,並有利於未來的可操作性和可維護性。

AOP 底層:動態代理。

如果是接口採用 JDK 動態代理,如果是類採用 CGLIB 方式實現動態代理。

AOP 的一些場景應用;

AOP 用來封裝橫切關注點,具體可以在下面的場景中使用:

Authentication 權限

Caching 緩存

Context passing 內容傳遞

Error handling 錯誤處理

Lazy loading 懶加載

Debugging調試

logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準

Performance optimization 性能優化

Persistence持久化

Resource pooling 資源池

Synchronization 同步

Transactions 事務

spring 注入的幾種方式
(1)構造方法注入

(2)setter 注入

(3)基於註解

Spring 中 Bean 的作用域有哪些

作用域:用於確定 spring 創建 bean 實例個數

取值(常用的兩個):

singleton 單例,默認值。prototype 多例,一個 bean 的定義可以有多個實例。每執行一次 getBean 將獲得一個實例。

請介紹一下 bean 的生命周期

(1)bean 定義:在配置文件裏面用來進行定義。

(2)bean 初始化:有兩種方式初始化:在配置文件中通過指定 init-method 屬性來完成實現
org.springframwork.beans.factory.InitializingBean 接口

(3)bean 調用:有三種方式可以得到 bean 實例,並進行調用

(4)bean 銷毀:銷毀有兩種方式使用配置文件指定的 destroy-method 屬性實現
org.springframwork.bean.factory.DisposeableBean 接口

Spring 中自動裝配的方式有哪些

no:不進行自動裝配,手動設置 Bean 的依賴關係。

byName:根據 Bean 的名字進行自動裝配。

byType:根據 Bean 的類型進行自動裝配。

constructor:類似於 byType,不過是應用於構造器的參數,如果正好有一個 Bean與構造器的參數類型相同則可以自動裝配,否則會導致錯誤。autodetect:如果有默認的構造器,則通過 constructor 的方式進行自動裝配,否則使用 byType 的方式進行自動裝配。

(自動裝配沒有自定義裝配方式那麼精確,而且不能自動裝配簡單屬性(基本類型、字符串等),在使用時應注意。)

@Resource 和 @Autowired 區別?分別用在什麼場景?

(1)共同點:兩者都可以寫在字段和 setter 方法上。兩者如果都寫在字段上,那麼就不需要再寫 setter 方法。

(2)不同點:

@Autowired

@Autowired為Spring提供的註解,需要導入包
org.springframework.beans.factory.annotation.Autowired;只按照 byType 注入。@Autowired 註解是按照類型(byType)裝配依賴對象,默認情況下它要求依賴對象必須存在,如果允許 null 值,可以設置它的 required 屬性為 false。如果我們想使用按照名稱(byName)來裝配,可以結合@Qualifier 註解一起使用。

@Resource

@Resource 默 認 按 照 ByName 自 動 注 入 , 由 J2EE 提 供 , 需 要 導 入 包javax.annotation.Resource。@Resource 有兩個重要的屬性:name 和 type,而 Spring將@Resource 註解的 name 屬性解析為 bean 的名字,而 type 屬性則解析為 bean的類型。所以,如果使用 name 屬性,則使用 byName 的自動注入策略,而使用type 屬性時則使用 byType 自動注入策略。如果既不制定 name 也不制定 type 屬性,這時將通過反射機制使用 byName 自動注入策略。

Hibernate 和 mybatis 的區別?

(1)兩者最大的區別

針對簡單邏輯,Hibernate 與 MyBatis 都有相應的代碼生成工具,可以生成簡單基本的 DAO 層方法。

針對高級查詢,MyBatis 需要手動編寫 SQL 語句,以及 ResultMap,而 Hibernate有良好的映射機制,開發者無需關心 SQL 的生成與結果映射,可以更專註於流程。

(2)開發難度對比

Hibernate 的開發難度大於 MyBatis,主要由於 Hibernate 比較複雜,龐大,學習周期比較長。

MyBatis 則相對簡單,並且 MyBatis 主要依賴於生氣了的書寫,讓開發者剛進更熟悉。

(3)sql 書寫比較

Hibernate 也可以自己寫 sql 來指定需要查詢的字段,但這樣就破壞了Hibernate 開發的簡潔性,不過 Hibernate 具有自己的日誌統計。

MyBatis 的 sql 是手動編寫的,所以可以按照要求指定查詢的字段,不過沒有自己的日誌統計,所以要藉助 Log4j 來記錄日誌。

(4)數據庫擴展性計較Hibernate 與數據庫具體的關聯在 XML 中,所以 HQL 對具體是用什麼數據庫
並不是很關心MyBatis 由於所有 sql 都是依賴數據庫書寫的,所以擴展性、遷移性比較差。

(5)緩存機制比較

Hibernate 的二級緩存配置在 SessionFactory 生成配置文件中進行詳細配置,然後再在具體的表對象映射中配置那種緩存。

MyBatis 的二級緩存配置都是在每個具體的表對象映射中進行詳細配置,這樣針對不同的表可以自定義不同的緩衝機制,並且 MyBatis 可以在命名空間中共享相同的緩存配置和實例,通過 Cache-ref 來實現。

兩者比較,因為 Hibernate 對查詢對象有着良好的管理機制,用戶無需關心 SQL,所以在使用二級緩存時如果出現臟數據,系統會報出錯誤提示。 而 MyBatis 在這一方面使用二級緩存時需要特別小心,如果不能完全去頂數據更新操作的波及範圍,避免 cache 的盲目使用,否則,臟數據的出現會給系統的正常運行帶來很大的隱患。

mybatis 是如何工作的?

一、Mybatis 工作原理圖

mybatis 原理圖如下所示:

二、工作原理解析

mybatis 應用程序通過 SqlSessionFactoryBuilder 從 mybatis-config.xml 配置文件(也可以用 Java 文件配置的方式,需要添加@Configuration)來構建 SqlSessionFactory(SqlSessionFactory 是線程安全的);

然後,SqlSessionFactory 的實例直接開啟一個 SqlSession,再通過 SqlSession 實例獲得 Mapper 對象並運行 Mapper 映射的 SQL 語句,完成對數據庫的 CRUD 和事務提交,之後關閉 SqlSession。說明:SqlSession 是單線程對象,因為它是非線程安全的,是持久化操作的獨享對象,類似 jdbc 中的 Connection,底層就封裝了 jdbc 連接。

詳細流程如下:

(1)、加載 mybatis 全局配置文件(數據源、mapper 映射文件等),解析配置文件,MyBatis 基於 XML 配置文件生成 Configuration,和一個個 MappedStatement(包括了參數映射配置、動態 SQL 語句、結果映射配置),其對應着標籤項。

(2)、SqlSessionFactoryBuilder 通過 Configuration 對象生成 SqlSessionFactory,用來開啟 SqlSession。

(3)、SqlSession 對象完成和數據庫的交互:

a、用戶程序調用 mybatis 接口層 api(即 Mapper 接口中的方法)

b、SqlSession 通過調用 api 的 Statement ID 找到對應的 MappedStatement 對象

c、通過 Executor(負責動態 SQL 的生成和查詢緩存的維護)將 MappedStatement對象進行解析,sql 參數轉化、動態 sql 拼接,生成 jdbc Statement 對象

d、JDBC 執行 sql。

e、藉助 MappedStatement 中的結果映射關係,將返回結果轉化成 HashMap、JavaBean 等存儲結構並返回。

Hibernate 對象有幾個狀態值?

Transient 瞬時 :對象剛 new 出來,還沒設 id,設了其他值。

Persistent 持久:調用了 save()、saveOrUpdate(),就變成 Persistent,有 id

Detached 脫管 : 當 session close()完之後,變成 Detached。

簡述 Springmvc 的流程;

spring 工作的流程

流程如下:(1)用戶發起請求到前端控制器(DispatcherServlet),該控制器會過濾出哪些請求可以訪問 Servlet、哪些不能訪問。就是 url-pattern 的作用,並且會加載springmvc.xml 配置文件。

(2)前端控制器會找到處理器映射器(HandlerMapping),通過 HandlerMapping完成 url 到 controller 映射的組件,簡單來說,就是將在 springmvc.xml 中配置的或者註解的 url 與對應的處理類找到並進行存儲,用 map<url,handler>這樣的方式來存儲。

(3)HandlerMapping 有了映射關係,並且找到 url 對應的處理器,HandlerMapping就會將其處理器(Handler)返回,在返回前,會加上很多攔截器。

(4)DispatcherServlet 拿到 Handler 后,找到 HandlerAdapter(處理器適配器),通過它來訪問處理器,並執行處理器。

(5)執行處理器

(6)處理器會返回一個 ModelAndView 對象給 HandlerAdapter

(7) 通 過 HandlerAdapter 將 ModelAndView 對 象 返 回 給 前 端 控 制 器(DispatcherServlet)

(8)前端控制器請求視圖解析器(ViewResolver)去進行視圖解析,根據邏輯視圖名解析成真正的視圖(jsp),其實就是將 ModelAndView 對象中存放視圖的名稱進行查找,找到對應的頁面形成視圖對象

(9)返回視圖對象到前端控制器。

(10)視圖渲染,就是將 ModelAndView 對象中的數據放到 request 域中,用來讓頁面加載數據的。

(11)通過第 8 步,通過名稱找到了對應的頁面,通過第 10 步,request 域中有了所需要的數據,那麼就能夠進行視圖渲染了。最後將其返回即可。

Springmvc 和 Springboot 有什麼區別?

Spring MVC 是基於 Spring 的一個 MVC 框架 ;

Spring Boot 是基於 Spring4 的條件註冊的一套快速開發整合包。

Springboot 為什麼配置簡單?(即它自動做了什麼操作才能簡化程序員的操作)
主要是使用了 spring3 之後提供的註解,來代替 xml 文件的配置,最核心的是以下兩個註解

@Configuration,標註在類上,相當於定義一個配置類,一份 spring 的配置文件

@Bean,類似於 spring 配置文件中的通過這兩個註解就可以用 java 代碼的方式來完成相關 spring 配置

持久層設計要考慮的問題有哪些?請談一下你用過的持久層框架都有哪些?

“持久”就是將數據保存到可掉電式存儲設備中以便今後使用,簡單的說,就是將內存中的數據保存到關係型數據庫、文件系統、消息隊列等提供持久化支持的設備中。持久層就是系統中專註於實現數據持久化的相對獨立的層面。

持久層設計的目標包括:

數據存儲邏輯的分離,提供抽象化的數據訪問接口。

數據訪問底層實現的分離,可以在不修改代碼的情況下切換底層實現。

資源管理和調度的分離,在數據訪問層實現統一的資源調度(如緩存機制)。

數據抽象,提供更面向對象的數據操作。

持久層框架有: Hibernate、MyBatis、TopLink、 Guzz、 jOOQ、 Spring Data、ActiveJDBC

需要更多技術文檔可以在後台私信【學習】

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

【其他文章推薦】

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

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

※超省錢租車方案

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

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