標籤: 銷售文案

  • 流產、死胎層出不窮 南蘇丹隱匿石油業環境報告 犧牲者至今未受保障

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

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

  • Gogoro擴點台中南投屏東,全台將有360個換電站

    Gogoro擴點台中南投屏東,全台將有360個換電站

    徹底改寫電動機車市場銷售紀錄的新創公司Gogoro,在短短兩年內已突破20,000 輛的銷售數字,並建置了300 多個電池交換站,充分展現了積極搶攻市場版圖的超高效率與決心。Gogoro 13 日宣布,將在4 月底開始投入在台中海線的3 個城鎮以及屏東地區首座換電站的設置;5 月底前則將進入南投。

    Gogoro 能源服務副總經理潘璟倫表示,Gogoro 在第一季的布站目標主要著力在高雄及台南地區,共於該區新增了19 個換電站。第二季,則會強化在六都以外的建置計畫,除預計在屏東市、東港、南投市、草屯、員林等地設置首座換電站外,也會在清水,沙鹿,大甲與鹿港4 個城鎮分別設置換電站以串連、打通台中彰化的海線。Gogoro 最南端的換電站,也預期在第二季末於東港設立。這些都是依據大數據分析的結果所進行的計畫,後續,大家也可以很快地可以看到在不同的區域,看到GoStation 電池交換站。

    在六都地區,Gogoro 仍以「一公里一座換電站」為能源網路目標,從北台灣一路往南延伸,透過與加油站、捷運站、學校、便利商店、賣場等單位異業結盟,合作布點的方式,積極擴大台灣綠色生活圈。

    依照Gogoro 第二季的計畫,6 月底前,全台將會有360 個換電站。這讓Gogoro 更貼近其將在2017 年底完成西岸走廊串連,讓基隆到屏東的西部都會區得以北南縱走,暢騎無阻的承諾。

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

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

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

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

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

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

    目前,英威騰電機控制器系列產品主要有純電動客車主電機控制器、混合動力客車主電機控制器、環衛車主電機控制器、物流車主電機控制器、輔助控制器及各種集成方案。其主電機控制器主要用於新能源汽車發電機與電動機的控制,可用來控制新能源汽車的非同步電機和永磁同步電機,實現高效、節能,控制器效率可達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/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

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

    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擴大充電網絡規模,供卓越充電體驗

    隨著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/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

    ※超省錢租車方案

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

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

  • 台達電佈局電動車產品,拓歐美電動車市場

    台達電佈局電動車產品,拓歐美電動車市場

    台達電於4月28日舉行法說會,公佈2017年第一季財報合併營收489.25億元新台幣,季減14%,年增2.8%;毛利率27.2%,季減0.06個百分點,年增0.26個百分點;因管控得宜,第一季匯兌收益1.4億元;稅後淨利39.19億元,每股盈餘1.51元,低於前一季的1.91元,略高於去年同期的1.50元。

    台達電執行長鄭平表示,公司5月起進行組織調整,擴大在電動車相關產品佈局,目前公司已打入歐美電動車廠,提供包括車載充電器、動力馬達、DC-DC轉換器等電動車零組件;在中國大陸也打入合資車廠,雖然電動車領域營收短期內成長幅度不大,但仍看好電動車領域未來長期的布局效益。

    台達電宣布組織調整,自2日起,將以「電源及零組件」、「自動化」與「基礎設施」為新三大業務範疇,其中,電源及零組件業務包括電動車方案事業群(EVSBG)、嵌入式電源系統事業群(EPSBG)、商用電源事業群(MPBG)、零組件事業群(CPBG)、風扇暨熱傳導事業群(FMBG);自動化業務包括機電事業群(IABG)、樓宇自動化事業群(BABG);至於基礎設施業務則包括資通訊基礎設施事業群(ICTBG)、能源基礎設施事業群(EISBG)。以新三大業務範疇區分,第一季電源及零組件占營收比重為55%、自動化占比為11%,基礎設施則占31%。

    對於未來營運展望,台達電董事長海英俊表示,第二季看好IA、樓宇自動化、數據中心的營運動能;今年雖然有匯率變數,但強調公司營運不會受到影響,並將持續朝向高毛利產品發展,讓毛利率能維持目前水準或更好。

    (本文內容由授權使用)  

     

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

    【其他文章推薦】

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

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

    ※回頭車貨運收費標準

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

    ※超省錢租車方案

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

  • 自動化主管請辭Tesla,市場憂電動車量產計畫

    自動化主管請辭Tesla,市場憂電動車量產計畫

    特斯拉(Tesla Inc.)負責自動化、工程專業的主管Klaus Grohmann,傳出因理念和執行長馬斯克(Elon Musk)不合,已經在3月份離職。市場擔憂,這恐怕會影響特斯拉電動車的量產計畫。

    路透社27日獨家報導(),特斯拉在2016年11月收購Grohmann創辦的Grohmann Engineering,原本打算靠著這家企業的自動化、工程專長,在2018年將電動車年產量拉升至50萬台。

    不過,消息人士透露,Grohmann跟馬斯克在如何對待現有客戶的問題上衝突不斷,是促使Grohmann離職的主因。據傳,馬斯克要求Grohmann把重心擺到特斯拉專案,將Grohmann Engineering原有客戶(如戴姆勒和BMW)的利益放到後頭。

    消息稱,特斯拉仍計畫運用Grohmann留下的技術和人員拉高產能,但部分人在創辦人離開後,對只仰賴一家客戶(也就是特斯拉)的作法感到相當不安。

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

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

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

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

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

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

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

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

    【其他文章推薦】

    ※超省錢租車方案

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

    ※回頭車貨運收費標準

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

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

  • 地球發燒了研究:2080年前熱死人數激增20倍

    摘錄自2018年8月1日蘋果日報台北報導

    天氣讓人熱得受不了,而這種情況若不加以控制,地球上熱死人的數目將增加20倍。最新研究指出,在各國政府完全不做任何事的最糟情況,部分國家在2080年前,因為高溫導致的死亡數字將增加2000%。

    這項刊登在「公共科學圖書館醫學期刊」(PLOS Medicine)的報告指出,歐洲、部分亞洲與北美洲地區的氣溫逐年升高,熱浪造成數以千計的死亡案例。該報告首席研究員、澳洲蒙納士大學(Monash University)副教授郭玉明(Yuming Guo,音譯)說:「未來的熱浪會發生得更頻繁、更強烈,維持時間也更長」、「如果我們找不到減緩氣候變遷的方法,並幫助人民適應熱浪氣候,和熱浪有關的死亡案例將會急遽增加。」

    報告中指出,最糟的情況下,哥倫比亞在2031至2080年間被高溫熱死的人數,會比1971年至2010年增加2000%,即增加20倍;菲律賓在2031到2080因熱浪而額外死亡的人數,是1971到2020的12倍;澳洲、美國是5倍,英國是4倍。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

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

  • 圖像處理中的valid卷積與same卷積

    valid卷積

    在full卷積的卷積過程中,會遇到\(K_{flip}\)靠近I的邊界(K矩陣與I矩陣),就會有部分延申到I之外,這時候忽略邊界,只考慮I完全覆蓋\(K_{flip}\)內的值情況,這個的過程就是valid卷積。一個高為H1,寬為W1的矩陣I與高為H2,寬為W2的矩陣K,在H1大於等於H2,W1大於等於W2的情況下,valid卷積的結果就是一個(H1-H2+1)*(W-W+1)的矩陣\(C_{valid}\)

    \[C_{valid}與C_{full}的對應關係為: C_{valid} = C_{full}( Rect (W_{2}-1,H_{2}-1,W_{1}-W_{2}+1,H_{1}-H_{2}+1) ) \]

    same卷積

    無論是full卷積還是valid卷積都不會得到正好的尺寸,要麼比原尺寸大要麼比原尺寸小,這時就需要same卷積來解決這個問題。若想得到寬和高都正好的矩陣我們首先需要給\(K_{flip}\)一個錨點,將錨點放在(循環)圖像矩陣的(r,c)處,((r,c)在矩陣之內),將對應位置的元素逐個相乘,最終將所有的積進行求和作為輸出圖像矩陣在(r,c)處的輸出值。這個過程稱為same卷積。
    OpenCv函數copyMakeBorder的參數表

    參數 解釋
    src 輸入矩陣
    dst 輸出矩陣
    top 上側擴充的行數
    bottom 下側擴充的行數
    left 左側擴充的行數
    right 右側擴充的行數
    borderType 邊界擴充的類型
    value border Type= BORDER_CONSTANT事的常數

    其中borderType有多種類型,比如:BORDER_REPLICATE(邊界複製)、BORDER_CONSTANT(常數擴充)、BORDER_REFLECT(反射擴充)等。
    在使用Python進行卷積操作時用到包Scipy,其中有關的操作函數為convolve2d(in1,in2,mode=’full’,boundary=’fill’,fillvalue=0)

    參數 解釋
    in1 輸入數組
    in2 輸入數組,代表K(卷積算子)
    mode 卷積類型,也就是以上提到的三種類型:full,valid,same
    boundary 邊界填充:fill\wrap\symm
    fillvalue 當boundary=’fill’時,設置邊界填充的值,默認為0

    在這裏需要注意的是當model為same時卷積算子的錨點位置由不同尺寸而不同,假設K(卷積算子)的寬和高分別為W、H。

    W和H的值 錨點位置
    均為奇數 默認為中心點
    H為偶數、W為奇數 (H-1,(W-1)/2)
    H為奇數,W為偶數 ((H-1)/2,W-1)
    均為偶數 (H-1,W-1)

    代碼實現:

    import numpy as np
    from scipy import signal
    
    if __name__ == "__main__":
    
        I = np.array([[1,2],[3,4],np.float32])
        #I的高和寬
        H1,W1 = I.shape[:2]
        #卷積算子
        k = np.array([[-1,-2],[2,1],np.float32])
        #K的寬和高
        H2,W2 = k.shape[:2]
        #計算full卷積
        c_full = signal.convolve2d(I,k,mode='full')
        #設定錨點
        r,c = 0,0
        #根據錨點來從full卷積中截取same卷積
        c_same= c_full[H2-r-1:H1-r-1,W2-c-1:W1+W2-c-1]
    

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

  • 面試必問系列之JDK動態代理

    面試必問系列之JDK動態代理

    掃描文末二維碼或者微信搜索公眾號小李不禿,即可關注微信公眾號,獲取到更多 Java 相關內容。

    1. 帶着問題去學習

    面試中經常會問到關於 Spring 的代理方式有哪兩種?大家異口同聲的回答:JDK 動態代理和 CGLIB 動態代理。

    這兩種代理有什麼區別呢?JDK 動態代理的類通過接口實現,CGLIB 動態代理是通過子類來實現的。

    那 JDK 動態代理你了到底了解多少呢?有去看過代理對象的 class 文件么?下面兩個關於 JDK 動態代理的問題你能回答上來么?

    • 問題1:為什麼 JDK 動態代理要基於接口實現?而不是基於繼承來實現?
    • 問題2:JDK 動態代理中,目標對象調用自己的另一個方法,會經過代理對象么

    小李帶着大家更深入的了解一下 JDK 的動態代理。

    2. JDK 動態代理的寫法

    • JDK 動態代理需要這幾部分內容:接口、實現類、代理對象。
    • 代理對象需要繼承 InvocationHandler,代理類調用方法時會調用 InvocationHandlerinvoke 方法。
    • Proxy 是所有代理類的父類,它提供了一個靜態方法 newProxyInstance 動態創建代理對象。
    public interface IBuyService {
         void buyItem(int userId);
         void refund(int nums);
    }

     

    @Service
    public class BuyServiceImpl implements IBuyService {
        @Override
        public void buyItem(int userId) {
            System.out.println("小李不禿要買東西!小李不禿的id是: " + userId);
        }
        @Override
        public void refund(int nums) {
            System.out.println("商品過保質期了,需要退款,退款數量 :" + nums);
        }
    }

     

    public class JdkProxy implements InvocationHandler {

        private Object target;
        public JdkProxy(Object target) {
            this.target = target;
        }
        // 方法增強
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before(args);
            Object result = method.invoke(target,args);
            after(args);
            return result;
        }
        private void after(Object result) { System.out.println("調用方法后執行!!!!" ); }
        private void before(Object[] args) { System.out.println("調用方法前執行!!!!" ); }

        // 獲取代理對象
        public <T> getProxy(){
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),this);
        }
    }

     

    public class JdkProxyMain {
        public static void main(String[] args) {
            // 標明目標 target 是 BuyServiceImpl
            JdkProxy proxy = new JdkProxy(new BuyServiceImpl());
            // 獲取代理對象實例
            IBuyService buyItem = proxy.getProxy();
            // 調用方法
            buyItem.buyItem(12345);
        }
    }

    查看運行結果

    調用方法前執行!!!!
    小李不禿要買東西!小李不禿的id是: 12345
    調用方法后執行!!!!

    我們完成了對目標方法的增強,開始對代理對象進行一個更全面的分析。

    3. 剖析代理對象並解答問題

    剖析代理對象的前提得是有代理對象,動態代理的對象是在運行時期創建的,我們就沒辦法通過打斷點的方式進行分析了。但是我們可以通過反編譯 .class 文件進行分析。如何獲取到 .class 文件呢?

    通過在代碼中添加:System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true") ,就能夠實現將動態代理對象的 class 文件寫入到磁盤中。代碼如下:

    public class JdkProxyMain {
        public static void main(String[] args) {
            // 代理對象的 class 文件寫入到磁盤中
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles""true");
            // 標明目標 target 是 BuyServiceImpl
            JdkProxy proxy = new JdkProxy(new BuyServiceImpl());
            // 獲取代理對象實例
            IBuyService buyItem = proxy.getProxy();
            // 調用方法
            buyItem.buyItem(12345);
        }
    }

    在項目的根目錄下多了一個 $Proxy0.class 文件

    看一下這個文件的內容

    public final class $Proxy0 extends Proxy implements IBuyService {
        private static Method m1;
        private static Method m3;
        private static Method m2;
        private static Method m4;
        private static Method m0;

        public $Proxy0(InvocationHandler var1) throws  {
            super(var1);
        }

        public final boolean equals(Object var1) throws  {
            try {
                return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }

        public final void buyItem(int var1) throws  {
            try {
                super.h.invoke(this, m3, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }

        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }

        public final void refund(int var1) throws  {
            try {
                super.h.invoke(this, m4, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }

        public final int hashCode() throws  {
            try {
                return (Integer)super.h.invoke(this, m0, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }

        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
                m3 = Class.forName("com.example.springtest.service.IBuyService").getMethod("buyItem", Integer.TYPE);
                m2 = Class.forName("java.lang.Object").getMethod("toString");
                m4 = Class.forName("com.example.springtest.service.IBuyService").getMethod("refund", Integer.TYPE);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }

    動態代理對象 $Proxy0 繼承了 Proxy 類並且實現了 IBuyService 接口。那問題 1 的答案就出來了:動態代理對象默認繼承了 Proxy 對象,而且 Java 不支持多繼承,所以 JDK 動態代理要基於接口來實現。

    $Proxy0 重寫了 IBuyService 接口的方法,還有 Object 的方法。在重寫的方法中,統一調用 super.h.invoke 方法。super 指的是 Proxyh 代表 InvocationHandler,這裏就是 JdkProxy。所以這裏調用的是 JdkProxyinvoke 方法。

    所以每次調用 buyItem 方法的時候,會先打印出 調用方法前執行!!!!

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    before(args);
    // 通過反射調用方法
    Object result = method.invoke(target,args);
    after(args);
    return result;
    }
    private void after(Object result) { System.out.println("調用方法后執行!!!!" ); }
    private void before(Object[] args) { System.out.println("調用方法前執行!!!!" ); }

    問題 2 還沒解決呢,接着往下看

    @Service
    public class BuyServiceImpl implements IBuyService {
        @Override
        public void buyItem(int userId) {
            System.out.println("小李不禿要買東西!小李不禿的id是: " + userId);
            refund(100);
        }
        @Override
        public void refund(int nums) {
            System.out.println("商品過保質期了,需要退款,退款數量 :" + nums);
        }
    }

    上面這段代碼中,在 buyItem 調用內部的 refund 方法,那這個內部調用方法是否走代理對象呢?看一下執行結果:

    調用方法前執行!!!!
    小李不禿要買東西!小李不禿的id是: 12345
    商品過保質期了,需要退款,退款數量 :100
    調用方法后執行!!!!

    確實是沒有走代理對象,其實我們期待的結果是下面這樣的

    調用方法前執行!!!!
    小李不禿要買東西!小李不禿的id是: 12345
    調用方法前執行!!!!
    商品過保質期了,需要退款,退款數量 :100
    調用方法后執行!!!!
    調用方法后執行!!!!

    那為什麼會造成這種差異呢?

    因為內部調用 refund 方法的調用,相當於 this.refund(100),而這個 this 指的是 BuyServiceImpl 對象,而不是代理對象,所以refund 方法沒有得到增強

    4. 總結和延伸

    • 本篇文章了解了 JDK 動態代理的使用,通過分析 JDK 動態代理生成對象的 class 文件,解決了兩個問題:

      • 問題1:為什麼 JDK 動態代理要基於接口實現?而不是基於繼承來實現?
      • 解答:因為 JDK 動態代理生成的對象默認是繼承 Proxy ,Java 不支持多繼承,所以 JDK 動態代理要基於接口來實現。
      • 問題2:JDK 動態代理中,目標對象調用自己的另一個方法,會經過代理對象么
      • 解答:內部調用方法使用的對象是目標對象本身,被調用的方法不會經過代理對象。
    • 我們知道了 JDK 動態代理內部調用是不走代理對象的。那對於 @Transactional 和 @Async 等註解不起作用是不是就搞清楚為啥了?

    • 因為 @Transactional@Async 等註解是通過 Spring AOP 來進行實現的,如果動態代理使用的是 JDK 動態代理,那麼在方法的內部調用該方法中其它帶有該註解的方法,由於此時調用的不是動態代理對象,所以註解失效

    • 上面這些問題就是 JDK 動態代理的缺點,那 Spring 如何避免這個問題呢?就是另個一個動態代理:CGLIB 動態代理,我會在下篇文章進行分析。

    5. 參考

    • https://juejin.im/post/5d8a0799f265da5b7a752e7c#heading-6
    • https://blog.csdn.net/varyall/article/details/102952365

    6. 猜你喜歡

    • JSON的學習和使用

    • 學習反射看這一篇就夠了

    • 併發編程學習(一)Java 內存模型

    掃描下方二維碼即可關注微信公眾號小李不禿,一起高效學習 Java。

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

    【其他文章推薦】

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

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

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

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

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