特斯拉百萬輛銷售達標,汽車大老:已經走上滅亡之路

特斯拉 4 月售出第 100 萬輛電動車,成為全球第一個達成此成就的公司;2020 年第一季財報也很亮眼,不過汽車大老 Bob Lutz 認為特斯拉已走上滅亡之路,且會崩壞得比預期更早。

電動車龍頭特斯拉(Tesla)2020 年第一季結束後,累計銷售車輛數來到 102 萬,其中 54 萬輛是 Model 3 和 Y,具里程碑意義的第 100 萬輛車是 3 月 10 日生產的 Model Y。

純電動車排行榜上,原本領先的 Nissan,目前銷售量停在約 50 萬輛,中國最暢銷的比亞迪銷量估計為 37 萬輛,如果算入插電式混合動力車,比亞迪銷量高達 75 萬輛,但基本上還是難以跟特斯拉相比。

Congratulations Tesla team on making our 1,000,000th car!!

— Elon Musk (@elonmusk)

 
▲ 馬斯克生氣之餘不忘發推慶祝第 100 萬輛車售出。

 

這項里程碑的喜訊,未能掩蓋馬斯克(Elon Musk)對加州政府遲遲未復工的不滿,他已宣布要將特斯拉總部搬離加州,甚至考慮把工廠也遷走,這對特斯拉來說可不是好消息,因為好不容易省下不必要的開銷,於過去兩季繳出亮眼的財報。

這世界有很多討厭特斯拉的人,但汽車大老魯茲(Bob Lutz)若排第二,沒人敢說自己是第一。魯茲是美國汽車界的傳奇人物,擔任過福特、克萊斯勒和通用汽車的高階領導人,橫跨三巨頭,在汽車界打滾 47 個年頭,他對馬斯克和特斯拉始終抱持負面觀點。他歸結出幾個特斯拉的不穩定因子,認為特斯拉已經「在滅亡的半路了」。

根據魯茲的看法,特斯拉有以下幾個致命問題:

  1. 特斯拉一直用低於成本的售價賣車。
  2. 鋰離子電池技術沒有競爭門檻,對手同樣在用。
  3. 所有競爭對手都將推出續航 300 英里的車款。
  4. 主要市場對電動車的補貼將陸續縮減。
  5. 所有車廠都被迫推出電動車,並削價競爭,但他們可以靠燃油車銷售彌補。
  6. 包攬所有生產的策略是錯誤的,無法培養自己的供應鏈並讓整個產業變好。

前兩點,魯茲可能不太對,特斯拉已繳出連續獲利成績,成本控制奏效,他們越過了空有銷售沒有獲利的困境;而特斯拉的核心技術,特別是電池,目前還是領先競爭者一大截,除非魯茲有得到一些特別消息,否則技術上,特斯拉依然穩坐龍頭。

比較值得思考的是最後兩點,如果單看電動車,特斯拉似乎打遍天下無敵手,但是競爭對手儘管整體銷售下滑,卻依然有龐大獲利,這些獲利會否縮短彼此間的技術差距,進而追上特斯拉的銷售成績?

此外,在日趨激烈的鋰電池競爭格局下,想要整車一條龍的特斯拉,或許能在電池技術持續領先,但那也代表未來需要持續投入龐大研發資本;另一方面,其他車廠將電池技術與車輛生產外包給供應商,分攤了資本支出成本,也降低了電池原料缺乏的風險。

魯茲的觀點雖然整體來說有些偏激,但也指出特斯拉在整個產業發展可能有的脆弱環節,究竟特斯拉會否如他預言,走上滅亡之路,相信不久之後答案就會揭曉。

(合作媒體:。首圖來源:)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

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

特斯拉股價創高,惟馬斯克坦言 Model Y 產能有待提升

新浪科技報導,電動車大廠特斯拉與先前新車型組裝初期的情況一樣,此次也面臨 Model Y 的組裝問題。特斯拉執行長馬斯克(Elon Musk)在給生產線員工發送的電子郵件中承認,Model Y 的生產遇到了問題,「我們需要加快提升 Model Y 產能,將整改(指已下生產線的新車還需要進行調整返工)需求降到最低,希望你們意識到這對特斯拉現在來說真的很重要」。

Model Y 是特斯拉在 2019 年 3 月發布的經濟型 SUV 車型,今年 1 月開始投產,3 月開始交付;目前 Model Y 只在加州工廠生產,但特斯拉上海工廠已啟動組裝項目,明年就會在上海投產。馬斯克在郵件中表示,目前 Model S、X 和 3 車型的組裝生產進展順利,只有 Model Y 的組裝和供應鏈依然存在問題,這也是新產品的常見問題;他強調,Model Y的組裝是目前生產和製造工程的頭等大事。

在此之前,Model 3 上市之初也出現組裝問題,甚至多次產能跳票,無法實現既定產量目標,導致 2018 年初特斯拉股價大幅下跌。不過,隨著陸版 Model 3 規模加快放量,昨日特斯拉股價創下歷史新高,收於 949.92 美元,市值達到 1,762 億美元。特斯拉 5 月陸版 Model 3 銷量達到 1 萬 1,095 輛,月增 205%,走出疫情和降價帶來的影響。

(本文由  授權轉載;首圖來源:)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

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

上海汽車城無人駕駛汽車測試基地舉行開園儀式

6月7日上午,由工信部批准的國內首個“國家智慧網聯汽車(上海)試點示範區”封閉測試區在嘉定舉行了開園儀式。測試基地可以為無人駕駛汽車提供綜合性的測試場地和功能要求,集多種測試功能場景、DSRC和LTE-V等V2X通訊技術、覆蓋安全、效率、資訊服務和新能源汽車應用等四類領域的封閉測試區(一期)正式投入運營。

此次開放的一期測試場地,建設了1個GPS差分基站、2座LTE-V通訊基站、16套DSRC和4套LTE-V路側單元、6個智慧紅綠燈和40個各類攝像頭,整個園區道路實現了北斗系統的釐米級定位和WIFI的全覆蓋,完成了隧道、林蔭道、加油/充電站、地下停車場、十字路口、丁字路口、圓形環島等模擬交通場景,可以為無人駕駛、自動駕駛和V2X網聯汽車提供29種場景的測試驗證。

據瞭解,上海國際汽車城將計畫到2020年,開發出覆蓋整個汽車城100平方公里的智慧網聯汽車綜合性典型城市的示範區,並探索連接與虹橋樞紐的共用交通走廊,這意味著中國的智慧聯網和無人駕駛汽車從國家戰略高度正式進入實操階段。

此次揭牌的“智慧網聯汽車標準規範測試與研究基地”也將成為中國智慧網聯汽車標準規範的承載主體,推動相關產品、技術標準走向成熟。示範區目前正在承擔和進行中的國家重大專項、上海市級重點專案18項,涉及公共服務平臺、資料中心、關鍵技術研究和標準規範制定等多個方面。

同時,作為國內首個智慧聯網和無人駕駛試點城市,將以嘉定為中心佈局汽車全產業鏈,嘉定也將成為中國智慧汽車和無人駕駛的國家級“孵化器”。

中國汽車技術中心“智慧網聯汽車標準規範測試與研究基地”揭牌後,未來智慧汽車和無人駕駛在滬已明確將完成“四步走”規劃:

第一階段是封閉測試階段,目前正在進行中。在嘉定汽車博覽公園、同濟大學嘉定校區等5平方公里範圍內,測試車輛達到200輛左右,封閉道路15公里,模擬智慧網聯汽車在高速+城市+鄉村試跑狀況;預計今年年內將進一步完善通訊網路、交通道路等基礎設施,演示場景增至50種,為智慧網聯以及無人駕駛等技術應用最終進入城市綜合示範區打下基礎。

第二階段是開放道路測試階段。從今年9月到明年底,將圍繞汽車城核心區博園路、墨玉南路、汽車•創新港等36個模擬封閉交通場景,實現1000輛車在27平方公里面積內73公里左右的車輛上路實測,最終實現國內首個功能完備的智慧網聯汽車測試示範公共服務平臺。

第三階段從2018年到2019年底,則將開始典型城市綜合示範區試驗。測試示範區的面積將在安亭汽車城核心區的基礎上拓展至安亭鎮全區,投入5000輛車在包括高速路在內的100平方公里範圍內試跑,基本建成基於智慧城市理念與要求下的智慧網聯汽車區域性測試示範公共服務平臺,初步打造智慧網聯汽車產業集群,成為全國區域性智慧網聯汽車標準化產業基地。

最後第四階段到2020年,真正在滬建成示範城市及交通走廊。以安亭到虹橋樞紐為中心,10000輛車的示範道路累計增加到約500公里,建設兩條共用走廊將兩個區域連接起來形成閉環,最終建成區域性、相對獨立、功能齊全的智慧網聯汽車測試示範公共服務平臺,形成初具規模的智慧網聯汽車產業集群。

資料顯示,在2015年10月,位於汽車城的一個占地面積12萬平方米的汽車智慧園區汽車•創新港正式開園,半年不到的時間內聚集了包括蔚來汽車、上汽阿裡斑馬汽車、樂視汽車等新型的造車企業迅速聚集於此。

 

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

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

特斯拉:Model 3 不太可能如期交車

3 月 31 對外發表「親民平價」電動車 Model 3 後,下單數量暴增,特斯拉〈Tesla〉在短短一周後狂接 32.5 萬筆訂單,最近一次公布的數字更高達 40 萬筆訂單,如此驚人的數字,不僅打破電動車市場紀錄,也挑戰了車業過往的訂單紀錄。於此同時,外界也在質疑,特斯拉真能準時出貨交車嗎?   這個答案恐怕要讓已經下訂 Model 3 的消費者失望了。特斯拉執行長馬斯克〈Elon Musk〉於 5 月 4 日表示,原先預期 Model 3 第一批訂於 2017 年 7 月 1 日交車,但因車輛出廠牽扯到供應鏈是否能如期交單,以及組裝時間是否如預期,因此,「Model 3 不太可能如期交車」。   馬斯克指出,Model 3 的設計上,沒有其他現有車款 Model S 與 Model X 複雜,但能否準時交車,還是得仰賴生產零件的供應鏈端是否如期交貨,若供應鏈無法達到預期目標,特斯拉會在位於加州費利蒙〈Fremont〉的生產工廠自行製造所需零件。   馬斯克預期,2017 年 Model 3 的初期生產量將達 10 萬至 20 萬輛,且 2018 年產出將擴增至 50 萬輛。   此外,為了讓全球的出貨更有效率,馬斯克提到,等到位於加州費利蒙的工達到最大化生產,可能會考慮在中國或歐洲設廠點,以滿足各地的出貨需求。

(首圖來源:)

(本文授權轉載自《》─〈〉)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

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

CSS(4)—三大特性(繼承性,層疊性,優先級)

CSS(4)—三大特性(繼承性,層疊性,優先級)

CSS有三大特性分別是: 繼承性,層疊性,優先級。

一、繼承性

概念 給父元素設置一些屬性,子元素也可以使用,這個我們就稱之為繼承性。

注意

1.並不是所有的屬性都可以繼承, 只有以color/font-/text-/line-開頭的屬性才可以繼承
2.在CSS的繼承中不僅僅是兒子可以繼承, 只要是後代都可以繼承
3.繼承性中的特殊性
   3.1 a標籤的文字顏色和下劃線是不能繼承的
   3.2 h標籤的文字大小是不能繼承的

示例

<!-- 樣式部分 -->
<style type="text/css">
    .father { 
         width: 300px;            /*設置寬度*/
         font-size: 20px;         /* 設置字體*/
         text-align: right;       /* 字體右對齊*/
         background-color: green; /*背景顏色綠色*/
         color:red; /*字體顏色紅色*/
     }
 </style>
 
<!-- html部分 -->
 <body>
    <div class="father">father標籤
      <p>father子標籤 p</p>
    </div>
  </body>

運行結果

從這個例子中可以看齣子標籤p繼承了父類div的樣式。

二、層疊性

概念 層疊性就是CSS處理衝突的一種能力。層疊性只有在多個選擇器選中 同一個標籤, 然後又設置了相同的屬性, 才會發生層疊性。

示例

<html>
<head>
    <title>CSS三大特性之層疊性</title>
    <style>
        p {
            color: red;
        }
        p {
            color: blue;
        }
    </style>
</head>
<body>
  <p style="color: black">我是段落</p> <!-- 最終显示black 就近原則 black > blue > red -->
</body>
</html>

在相同優先級的的情況下 下面的樣式元素會將上面的層疊掉。

三、CSS優先級

概念 當多個選擇器選中同一個標籤, 並且給同一個標籤設置相同的屬性時, 如何層疊就由優先級來確定。

優先級

!important>行內樣式>id選擇器>類選擇器>標籤選擇器>通配符>繼承 

補充說明

1、繼承樣式的權重為0。即在嵌套結構中,不管父元素樣式的權重多大,被子元素繼承時,他的權重都為0,也就是說子元素定義的樣式會覆蓋繼承來的樣式。
2、行內樣式優先。應用style屬性的元素,其行內樣式的權重非常高,可以理解為遠大於100。
3、權重相同時,CSS遵循就近原則。也就是說靠近元素的樣式具有最大的優先級,或者說排在最後的樣式優先級最大。
4、CSS定義了一個!important命令,該命令被賦予最大的優先級。也就是說不管權重如何以及樣式位置的遠近,!important都具有最大優先級。

關於CSS權重,有一套計算公式來去計算,用一個四位的數 字串(CSS2是三位)來表示,更像四個級別,值從左到右,左面的最大,一級大於一級,數位之間沒有進制,級別之間不可超越。

部分權重是可以疊加的。比如的例子:

div ul  li   ------>      0,0,0,3
a:hover      -----—>      0,0,1,1
.son ul li   ------>      0,0,1,2
.son a       ------>      0,0,1,1   
#son p       ------>      0,1,0,1

注意

對於並集選擇器來說不是權重的加和,因為理論上它還是獨立的,它只相當於將多個選擇器的相同內容歸於一個並集選擇器中,理論上每一個選擇器還是獨立的。

示例

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
        div,p {
            color: green; /*這裏不能是0,0,0,2 而是兩個0,0,0,1*/
        }

        p {
            color: red;  /*對於p標籤最終會显示紅色 0,0,0,1 (因為和上面優先級一樣,所以下面會覆蓋上面樣式)*/
        }
    </style>
</head>
<body>
    <p>標籤什麼顏色</p>
</body>
</html>

四、經典測試題

這裏舉幾個測試題來鞏固下css優先級的知識。首先我們要知道如何推斷標籤的最終樣式

1. 先找到影響文字的最裏面的盒子
2. 然後計算權重
3. 如果權重一樣,看層疊性

1、第一題

<!DOCTYPE>
<html>
    <head>
        <title>第2題</title>
        <style type="text/css">
            #father{
                color:red;  /* 繼承的權重為 0,0,0,0 */
            }
            p{
                color:blue;  /* 權重 0,0,0,1 */
            }
        </style>
    </head>
    <body>
        <div id="father">
            <p>試問這行字體是什麼顏色的?</p>
        </div>
    </body>
</html>

答案 藍色。

2、第二題

<!DOCTYPE>
<html>      
    <head>
        <title>第1題</title>
        <style type="text/css">
            #father #son{    /*權重: 0,2,0,0 */
                color:blue;
            }
            #father p.c2{   /* 權重: 0,1,1,1 */
                color:black;
            }
            div.c1 p.c2{    /* 權重 0,0,2,2 */
                color:red;
            }
            #father{
                color:green !important;  /* 繼承的權重為 0,0,0,0 */
            }
        </style>
    </head>
    <body>
        <div id="father" class="c1">
            <p id="son" class="c2">
                試問這行字體是什麼顏色的?
            </p>
        </div>
    </body>
</html>

答案 藍色。

3、第三題

<!DOCTYPE>
<html>
<head>
    <title>Document</title>
    <style type="text/css">
        div div div div div div div div div div div div{  /* 權重 0,0,0,11 (最後一位數再怎麼相加都不會向前進一位) */
            color:red;
        }
        .me{ 
            color:blue; /* 權重 0,0,1,0 */
        }
    </style>
</head>
<body>
    <div>
        <div>
            <div>
                <div>
                    <div>
                        <div>
                            <div>
                                <div>
                                    <div>
                                        <div>
                                            <div>
                                                <div class="me">試問這行文字是什麼顏色的</div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

答案 藍色。

4、第四題

<!DOCTYPE>
<html>
<head>
    <title>第四題</title>
    <style type="text/css">
        .c1 .c2 div{       /* 權重 0,0,2,1 */
            color: blue;
        }
        div #box3{         /* 權重 0,1,0,1 */
            color:green;
        }
        #box1 div{         /* 權重 0,1,0,1 */
            color:yellow;
        }
    </style>
</head>
<body>
    <div id="box1" class="c1">
        <div id="box2" class="c2">
            <div id="box3" class="c3">
                文字显示什麼顏色
            </div>
        </div>
    </div>
</body>
</html>

答案 黃色 (如果權重一樣,看層疊性)

你如果願意有所作為,就必須有始有終。(6)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

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

和諧富騰挖角Volvo高階主管,2017衝首款平民電動車

由鴻海、騰訊集團與和諧汽車聯手打造的中國電動車公司和諧富騰,致力於推動「互聯網+智慧電動車」。市場上傳出和諧富騰將延攬富豪汽車(Volvo)主管,目標在2017年推出首款平名電動車。

和諧富騰分別由和諧汽車持股接近四成、騰訊與鴻海各持股29.4%,為2015年於中國鄭州成立的合資公司,初期資本額為人民幣10億元,主要業務為電動車的生產、製造;研發與製造工作主要由鴻海負責。

目前,和諧富騰旗下有兩大子品牌:愛車、愛迪生,為雙品牌經營。其中,愛車將以推動平民款電動車iCar為主要任務。愛車有55%由和諧富騰出資,28%由和諧汽車出資,17%則為戰略合作夥伴出資。

自成立以來,和諧富騰就積極於打造自己的高階團隊,從BMW、Google自動駕駛團隊等挖角人手。目前,和諧富騰執行長由有「BMW i8電動跑車之父」的Carsten Breitfeld擔任,營運長則由有「中國豪車通」美名的Daniel Kirchert擔任。外媒近日報導,和諧富騰將延攬Volvo前中國總裁兼執行長付強加入,擔任愛車公司的執行長。

和諧富騰希望付強加入愛車公司後,能加速推動iCar的製造與行銷腳步,目標在2017年推出首輛iCar產品。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

LNMP+Redis架構部署

工作機制

  • L(Linux)N(Nginx)M(Mysql)P(PHP)架構想必大家都知道,LNMP架構主要作用是讓前端服務與後端存儲以及後端的一下服務進行連接起來,來實現php程序的動態請求。

   而今天我們又在LNMP架構上面加一個Redis程序,而Redis在整個架構中起到了一個數據緩存的作用。

  • LNMP+Redis工作機制:當用戶通過瀏覽器訪問網站時,並使用賬號密碼進行登陸時,此時會向Redis發出查詢請求,若Redis緩存中沒有相關信息,則php會查詢mysql數據庫中的相關信息,然後將相關信息緩存在redis中;在下次此用戶訪問時,php無需再從mysql數據庫中讀取數據,直接從redis中讀取緩存並將數據返回,這樣就可以減少數據庫的讀取壓力。
  • 下面是簡單的工作機制示意圖

 

系統環境描述

  • Linux系統版本:我這裏使用的是Ubuntu系統,大家可以選用不同的Linux版本
   jia@uduntu:~$ lsb_release -a

    No LSB modules are available.
    Distributor ID: Ubuntu
    Description: Ubuntu 19.10
    Release: 19.10
    Codename: eoan

  • Nginx軟件版本
  nginx/1.16.1 (Ubuntu)
  •  PHP軟件版本
   7.3.11-0ubuntu0.19.10.1 amd64
  • MariaDB軟件版本
   1:10.3.17-1 all

 

  • Redis軟件版本
   5:5.0.5-2build1 all

 

部署Nginx

Nginx描述:Nginx (engine x) 是一個高性能的HTTP和反向代理web服務器,同時也提供了MAP/POP3/SMTP服務。Nginx是一款輕量級的Web 服務器/反向代理服務器及电子郵件(IMAP/POP3)代理服務器,在BSD-like 協議下發行。其特點是佔有內存少,併發能力強,事實上nginx的併發能力在同類型的網頁服務器中表現較好。

安裝

安裝Nginx軟件包有很多種方法比如:RPM包安裝、編譯安裝等,我在這裏軟件就全部使用RPM進行安裝了

jia@uduntu:~$ sudo apt -y install nginx

    Setting up fonts-dejavu-core (2.37-1) ...
    Setting up libjpeg-turbo8:amd64 (2.0.3-0ubuntu1) ...
    Setting up libjpeg8:amd64 (8c-2ubuntu8) ...    
    Setting up libnginx-mod-mail (1.16.1-0ubuntu2) ...
    Setting up fontconfig-config (2.13.1-2ubuntu2) ...
    Setting up libnginx-mod-stream (1.16.1-0ubuntu2) ...
    Setting up libtiff5:amd64 (4.0.10+git191003-1) ...
    Setting up libfontconfig1:amd64 (2.13.1-2ubuntu2) ...
    Setting up libgd3:amd64 (2.2.5-5.2) ...
    Setting up libnginx-mod-http-image-filter (1.16.1-0ubuntu2) ...
    Setting up nginx-core (1.16.1-0ubuntu2) ...
    Setting up nginx (1.16.1-0ubuntu2) ...
    Processing triggers for ufw (0.36-1ubuntu3) ...
    Processing triggers for systemd (242-7ubuntu3) ...
    Processing triggers for man-db (2.8.7-3) ...
    Processing triggers for libc-bin (2.30-0ubuntu2) ...
jia@uduntu:
~$

 

出現上面字符即為安裝成功

啟動

程序啟動有兩種方法

  1. 作為系統服務進行啟動,啟動方法:

Ubuntu以及rhel7以上版本使用下面方式:

    systemctl  start nginx        \\啟動Nginx
    systemctl  stop  nginx        \\停止Nginx
    systemctl  restart  nginx        \\重新啟動Nginx

 

rhel7一下版本使用下面方式:

    server  nginx  start        \\啟動Nginx
    server  nginx  stop            \\停止Nginx
    server  nginx  restart        \\重新啟動Nginx

 

  1. 使用Nginx啟動腳本進行控制Nginx啟停:
    sh nginx        \\啟動Nginx
    停止nginx可以使用結束進程的方式進行停止

 

測試並訪問

接下來讓我們啟動nginx並進行訪問:

jia@uduntu:~$ systemctl start nginx        \\我這裏使用的非root用戶所以要求輸入密碼
    ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
    Authentication is required to start 'nginx.service'.
    Authenticating as: jia
    Password: 
    ==== AUTHENTICATION COMPLET
jia@uduntu:~$

 

啟動成功后訪問:
訪問地址:

    http://Server IP Address

 

看到下面內容證明安裝並啟動成功:

部署PHP

PHP描述:PHP即“超文本預處理器”,是一種通用開源腳本語言。PHP是在服務器端執行的腳本語言,與C語言類似,是常用的網站編程語言。PHP獨特的語法混合了C、Java、Perl以及 PHP 自創的語法。利於學習,使用廣泛,主要適用於Web開發領域。

安裝

    jia@uduntu:~$ sudo apt -y install php php7.3-fpm
    [sudo] password for jia:             //這裏正常輸入密碼
        \\安裝最後出現下面顯示錶示安裝成功
    Creating config file /etc/php/7.3/mods-available/json.ini with new version
    Setting up php7.3-readline (7.3.11-0ubuntu0.19.10.1) ...

    Creating config file /etc/php/7.3/mods-available/readline.ini with new version
    Setting up php7.3-cli (7.3.11-0ubuntu0.19.10.1) ...
    update-alternatives: using /usr/bin/php7.3 to provide /usr/bin/php (php) in auto mode
    update-alternatives: using /usr/bin/phar7.3 to provide /usr/bin/phar (phar) in auto mode
    update-alternatives: using /usr/bin/phar.phar7.3 to provide /usr/bin/phar.phar     (phar.phar) in auto mode

    Creating config file /etc/php/7.3/cli/php.ini with new version
    Setting up php7.3-fpm (7.3.11-0ubuntu0.19.10.1) ...

    Creating config file /etc/php/7.3/fpm/php.ini with new version
    Created symlink /etc/systemd/system/multi-user.target.wants/php7.3-fpm.service →     /lib/systemd/system/php7.3-fpm.service.
    Setting up php7.3 (7.3.11-0ubuntu0.19.10.1) ...
    Setting up php (2:7.3+69ubuntu2) ...
    Processing triggers for man-db (2.8.7-3) ...
    Processing triggers for systemd (242-7ubuntu3) ...

 

啟動

上面已經給大家說過Nginx的啟動方法了,php啟動方法與Nginx基本一樣

jia@uduntu:~$ systemctl start  php7.3-fpm
    ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
    Authentication is required to start 'php7.3-fpm.service'.
    Authenticating as: jia
    Password:             \\輸入密碼
    ==== AUTHENTICATION COMPLETE ===
jia@uduntu:~$ 

 

啟動成功,可以使用查看進程的方式進行查看

jia@uduntu:~$ ps uax | grep php            \\下面進程表示php運行進程
    root      10346  0.0  2.5 193732 17384 ?        Ss   08:29   0:00 php-fpm: master process     (/etc/php/7.3/fpm/php-fpm.conf)
    www-data  10357  0.0  0.9 194044  6348 ?        S    08:29   0:00 php-fpm: pool www
    www-data  10358  0.0  0.9 194044  6348 ?        S    08:29   0:00 php-fpm: pool www
    jia       10572  0.0  0.1   6296   920 pts/0    S+   08:33   0:00 grep --color=auto php
jia@uduntu:~$

 

配置Nginx

php啟動成功後下面配置Nginx,讓Nginx接收到的php請求轉交給php服務器進行解析
nginx配置文件:

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html index.php ;        \\此處需要在後面添加index.php
        server_name _;
        location / {
        try_files $uri $uri/ =404;
        }
        location ~ \.php$ {            \\取消註釋
               include snippets/fastcgi-php.conf;        \\取消註釋
               fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;        \\這一行和下面一行指的是php偵聽方式,查看php是偵聽那種方式然後取消註釋哪一行
               fastcgi_pass 127.0.0.1:9000;            \\
        }

在php-fpm配置文件種查看php的偵聽方式:

    listen = /run/php/php7.3-fpm.sock        \\這種偵聽方式適用於本地php
    listen = 127.0.0.1:9000        \\這種偵聽方式適用於遠程PHP

 

看你的那個php是那種方式偵聽的,然後將nginx配置文件中的一行取消註釋,然後再重新啟動nginx使改動生效

測試

默認網頁代碼的存放位置:

    /var/www/html

 測試只需要將index,html該名為index.php,內容更改為你的php代碼
我的php代碼內容為:

    <?php
        phpifo();
    ?>

 

下面來訪問一下,訪問地址不變

只要可以解析PHP代碼了就表示配置安裝成功

部署MariaDB

部署MariaDBMariaDB描述:MariaDB數據庫管理系統是MySQL的一個分支,主要由開源社區在維護,採用GPL授權許可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能輕鬆成為MySQL的代替品。MariaDB基於事務的Maria存儲引擎,替換了MySQL的MyISAM存儲引擎,它使用了Percona的 XtraDB,InnoDB的變體,分支的開發者希望提供訪問即將到來的MySQL 5.4 InnoDB性能。這個版本還包括了 PrimeBase XT (PBXT) 和 FederatedX存儲引擎。

安裝

 jia@uduntu:~$ sudo apt -y install mariadb-server
    Setting up mariadb-client-10.3 (1:10.3.17-1) ...
    Setting up libdbd-mysql-perl:amd64 (4.050-2build1) ...
    Setting up libhtml-parser-perl (3.72-3build2) ...
    Setting up mariadb-server-10.3 (1:10.3.17-1) ...
    Created symlink /etc/systemd/system/mysql.service → /lib/systemd/system/mariadb.service.
    Created symlink /etc/systemd/system/mysqld.service → /lib/systemd/system/mariadb.service.
    Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service → /lib/systemd/system/mariadb.service.
    Setting up libhttp-message-perl (6.18-1) ...
    Setting up libcgi-pm-perl (4.44-1) ...
    Setting up libhtml-template-perl (2.97-1) ...
    Setting up mariadb-server (1:10.3.17-1) ...
    Setting up libcgi-fast-perl (1:2.15-1) ...
    Processing triggers for systemd (242-7ubuntu3) ...
    Processing triggers for man-db (2.8.7-3) ...
    Processing triggers for libc-bin (2.30-0ubuntu2) ...
jia@uduntu:~$            \\出現上面代碼錶示安裝成功

 

啟動

同Nginx:

 jia@uduntu:~$ systemctl start mariadb
    ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
    Authentication is required to start 'mariadb.service'.
    Authenticating as: jia
    Password:         \\此處輸入密碼
    ==== AUTHENTICATION COMPLETE ===
 jia@uduntu:~$ 

 

查看是否啟動成功:

 jia@uduntu:~$ ps uax | grep mysqld
    mysql     11669  0.2 11.5 1713056 78488 ?       Ssl  09:17   0:00 /usr/sbin/mysqld
    jia       12614  0.0  0.1   6296   924 pts/0    S+   09:23   0:00 grep --color=auto mysqld
 jia@uduntu:~$ 

 

初始化數據庫:

 jia@uduntu:~$ sudo mysql_secure_installation 
     \\下面是初始化過程
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
jia@uduntu:~$ 

 

初始化完成后,可直接使用自帶的mysql客戶端進行連接

 jia@uduntu:~$ sudo mysql -u root -p
    Enter password: 
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MariaDB connection id is 56
    Server version: 10.3.17-MariaDB-1 Ubuntu 19.10

    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

    MariaDB [(none)]> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | ifnormation_schema |
    | mysql              |
    | performance_schema |
    +--------------------+
    3 rows in set (0.000 sec)

     MariaDB [(none)]> 

配置php支持

安裝php連接數據庫的中間件:php-mysql

 jia@uduntu:~$ sudo apt -y install php-mysql
    Preparing to unpack .../php-mysql_2%3a7.3+69ubuntu2_all.deb ...
    Unpacking php-mysql (2:7.3+69ubuntu2) ...
    Setting up php7.3-mysql (7.3.11-0ubuntu0.19.10.1) ...

    Creating config file /etc/php/7.3/mods-available/mysqlnd.ini with new version

    Creating config file /etc/php/7.3/mods-available/mysqli.ini with new version

    Creating config file /etc/php/7.3/mods-available/pdo_mysql.ini with new version
    Setting up php-mysql (2:7.3+69ubuntu2) ...
    Processing triggers for php7.3-fpm (7.3.11-0ubuntu0.19.10.1) ...
jia@uduntu:~$             //安裝成功

 

配置php.ini文件,將配置文件中extension=mysqli這一行取消註釋就可以了,然後重新啟動php-fpm

 jia@uduntu:/etc/php/7.3/fpm$ systemctl restart php7.3-fpm
    ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
    Authentication is required to restart 'php7.3-fpm.service'.
    Authenticating as: jia
    Password:             \\輸入密碼
    ==== AUTHENTICATION COMPLETE ===
 jia@uduntu:/etc/php/7.3/fpm$ 

測試

測試php是否可使用數據庫,最好的方法就是使用php代碼寫一個連接數據庫就可以了
代碼如下:

    <?php
        $host = "localhost";    //mysql主機
        $user = "root";            //mysql用戶
        $passwd = "redhat";        //mysql密碼
        $conn = new mysqli($host,$user,$passwd);
        if (!$conn){
            die("連接數據庫失敗");
        }
        echo "連接數據庫成功";        
    ?>

 

显示數據庫連接成功示安裝成功

部署Redis

Redis描述:Redis(全稱:Remote Dictionary Server 遠程字典服務)是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。

安裝

jia@uduntu:~$ sudo apt -y install redis                \\出現下面提示表示安裝成功
    Setting up lua-cjson:amd64 (2.1.0+dfsg-2.1) ...
    Setting up libatomic1:amd64 (9.2.1-9ubuntu2) ...
    Setting up lua-bitop:amd64 (1.0.2-5) ...
    Setting up liblua5.1-0:amd64 (5.1.5-8.1build3) ...
    Setting up libhiredis0.14:amd64 (0.14.0-3) ...
    Setting up redis-tools (5:5.0.5-2build1) ...
    Setting up redis-server (5:5.0.5-2build1) ...
    Created symlink /etc/systemd/system/redis.service → /lib/systemd/system/redis-                                        server.service.
    Created symlink /etc/systemd/system/multi-user.target.wants/redis-server.service →     /lib/systemd/system/redis-server.service.
    Setting up redis (5:5.0.5-2build1) ...
    Processing triggers for systemd (242-7ubuntu3) ...
    Processing triggers for man-db (2.8.7-3) ...
    Processing triggers for libc-bin (2.30-0ubuntu2) ...
jia@uduntu:~$ 

 

啟動

啟動等同於Nginx啟動

jia@uduntu:~$ sudo systemctl start redis

 

啟動成功後進行檢查

jia@uduntu:~$ sudo netstat -anpl |  grep redis
    tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN          2094/redis-server 1 
    tcp6       0      0 ::1:6379                :::*                    LISTEN          2094/redis-server 1 
jia@uduntu:~$ 

可以看到redis端口(6379)就證明啟動成功
下面讓我們使用redis客戶端測試一下:

jia@uduntu:~$ sudo redis-cli         \\啟動redis客戶端
    127.0.0.1:6379> set test "hellow word"            \\設置變量
        OK
    127.0.0.1:6379> get test        \\輸出變量
        "hellow word"
    127.0.0.1:6379> del test        \\刪除變量
        (integer) 1
    127.0.0.1:6379> get test    
        (nil)
    127.0.0.1:6379> 

 

上面測試可以看出redis安裝成功,並啟動成功

配置php支持

安裝php連接redis中間件

jia@uduntu:~$ sudo apt -y install php-redis                \\輸出以下內容表示安裝成功
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    The following additional packages will be installed:
      php-igbinary
    The following NEW packages will be installed:
      php-igbinary php-redis
    0 upgraded, 2 newly installed, 0 to remove and 18 not upgraded.
    Needto get 239 kB of archives.
    After this operation, 1,052 kB of additional disk space will be used.
    Get:1 http://cn.archive.ubuntu.com/ubuntu eoan/universe amd64 php-igbinary amd64 3.0.0-    1build1 [101 kB]
    Get:2 http://cn.archive.ubuntu.com/ubuntu eoan/universe amd64 php-redis amd64 5.0.2+4.3.0-2build1 [138 kB]
    Fetched 239 kB in 13s (19.0 kB/s)                                                                                  
    Selecting previously unselected package php-igbinary.
    (Reading database ... 70748 files and directories currently installed.)
    Preparing to unpack .../php-igbinary_3.0.0-1build1_amd64.deb ...
    Unpacking php-igbinary (3.0.0-1build1) ...
    Seleting previously unselected package php-redis.
    Preparing to unpack .../php-redis_5.0.2+4.3.0-2build1_amd64.deb ...
    Unpacking php-redis (5.0.2+4.3.0-2build1) ...
    Setting up php-igbinary (3.0.0-1build1) ...
    Setting up php-redis (5.0.2+4.3.0-2build1) ...
jia@uduntu:~$ 

 

安裝成功后,配置php支持redis
找到php.ini這個配置文件,添加下面配置,找到exension=mysql這一條,然後將下面代碼粘貼到下一行

    extension=redis.so

 

測試

測試php是否可以使用redis,下面頁面簡單既可以進行測試

<?php
   $redis = new Redis();        \\redis連接參數
   $redis->connect('127.0.0.1', 6379);        \\括號內第一項是指的redis server ip,第二項是 redis port
   echo "Connection to server successfully </br>";
   echo "Server is running: " . $redis->ping();
?>

 

將/var/www/html下面的index.php文件內容替換為上面內容,然後直接訪問即可
連接地址:

    http://nginx server ip

 

显示下面內容表示連接成功

Connection to server successfully
Server is running: 1

 

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

日產燃料電池車進化,結合生質能每趟可跑800公里

日產汽車(Nissan)日前發表新氫燃料電池車(FCV)技術,結合生質能燃料的「e-Bio Fuel-Cell」。充填燃料後,每趟最高可行駛800公里,較日產現行電動車Leaf的280公里續航力高上三倍。

e-Bio Fuel-Cell 以甘蔗、玉米等植物所生產的生物乙醇做為燃料,將生物乙醇透過改質器分解出氫和二氧化碳,再用電池堆進行氫氧化學反應並產生電力。由於生質能原料在成長過程中會吸收二氧化碳,因此整套能量循環是碳中和的。

最特別的是,e-Bio Fuel-Cell採用固態氧化物燃料電池(SOFC)做為車用電池堆,充填一次燃料最高可行駛800公里,每公里行駛費用估計僅約3.1日圓,與電動車的2.9日圓相差不多、而遠低於汽油車的9日圓。

日產已開始測試新款FCV,計畫率先將e-Bio Fuel-Cell技術應用於宅配等領域的商用車輛上,預計在2020年投入市場。屆時希望將開賣時的車輛售價壓低到一般電動車的水準。

《日經》指出,未來新能源汽車的版圖主要將分為以特斯拉(Tesla)為首的純電動車,以及以豐田、本田為主的FCV汽車等兩大陣營。豐田汽車已推出燃料電池車Mirai,本田也推出了Clarity Fuel Cell,皆以高純度氫為燃料。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

中國大陸電動車銷量年增169% 私家車成長幅度大

大陸公安部交管局公布,截至去(2015)年底,大陸機動車保有量達2.79億輛,其中汽車1.72億輛。在新能源汽車部分,截至去年底,大陸新能源汽車保有量已達58.32萬輛,年增169.48%;其中,純電動汽車保有量33.2萬輛,占56.93%,其保有量與2014年相比增幅達317.06%。

隨著大陸經濟持續發展,民眾購車剛性需求旺盛,汽車保有量繼續呈快速增長趨勢,去年新註冊登記的汽車達2,385萬輛,保有量淨增1,781萬輛,均為歷史最高水準。汽車占機動車的比率迅速提高,近5年汽車占機動車比率從47.06%提高到61.82%。

大陸全國已有40個城市的汽車保有量超過百萬輛,北京、成都、深圳、上海、重慶、天津、蘇州、鄭州、杭州、廣州、西安等11個城市汽車保有量超過200萬輛。

截至去年底,大陸小型載客汽車達1.36億輛,其中,私家車達1.24億輛,占91.53%;與2014年相比,私家車增加1,877萬輛,增長17.77%。全國平均每百戶家庭擁有31輛私家車,北京、成都、深圳等大城市每百戶家庭擁有私家車超過60輛。

(本文內容由授權使用)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

[ASP.NET Core 3框架揭秘] 依賴注入[9]:實現概述

《》、《》和《》主要從實現原理的角度對.NET Core的依賴注入框架進行了介紹,接下來更進一步,看看該框架的總體設計和實現。在過去的多個版本更迭過程中,依賴注入框架的底層實現一直都在發生改變,加上底層的涉及的大都是內容接口和類型,所以我們不打算涉及太過細節的層面。

一、ServiceProviderEngine & ServiceProviderEngineScope

對於依賴注入的底層設計和實現來說,ServiceProviderEngine和ServiceProviderEngineScope是兩個最為核心的類型。顧名思義,ServiceProviderEngine表示提供服務實例的提供引擎,服務實例最終是通過該引擎提供的,在一個應用範圍內只存在一個全局唯一的ServiceProviderEngine對象。ServiceProviderEngineScope代表服務範圍,它利用對提供服務實例的緩存實現對生命周期的控制。ServiceProviderEngine實現了接口IServiceProviderEngine,從如下的代碼片段可以看出,一個ServiceProviderEngine對象同時也是一個IServiceProvider對象,還是一個IServiceScopeFactory對象。

internal interface IServiceProviderEngine :  IServiceProvider, IDisposable, IAsyncDisposable
{
    void ValidateService(ServiceDescriptor descriptor);
    IServiceScope RootScope { get; }
}

internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory
{
    public IServiceScope RootScope { get; }    
    public IServiceScope CreateScope();
    ...
}

ServiceProviderEngine的RootScope屬性返回的IServiceScope對象是為根容器提供的服務範圍。作為一個IServiceScopeFactory對象,ServiceProviderEngine的CreateScope會創建一個新的服務範圍,這兩種服務範圍都通過一個ServiceProviderEngineScope對象來表示。

internal class ServiceProviderEngineScope : IServiceScope, IDisposable,  IServiceProvider, IAsyncDisposable
{
    public ServiceProviderEngine Engine { get; }
    public IServiceProvider ServiceProvider { get; }
    public object GetService(Type serviceType);
}

如上面的代碼片段所示,一個ServiceProviderEngineScope對象不僅是一個IServiceScope對象,還是一個IServiceProvider對象。在《》中,我們說表示服務範圍的IServiceScope對象是對一個表示依賴注入容器的IServiceProvider對象的封裝,實際上兩者合併為同一個ServiceProviderEngineScope對象,一個ServiceProviderEngineScope對象的ServiceProvider屬性返回的就是它自己。換句話說,我們所謂的子容器和它所在的服務範圍引用的都是同一個ServiceProviderEngineScope對象。

下圖進一步揭示了ServiceProviderEngine和ServiceProviderEngineScope之間的關係。對於一個通過調用ServiceProviderEngine對象的CreateScope創建的ServiceProviderEngineScope來說,由於它同時也是一個IServiceProvider對象,如果我們調用它的GetService<IServiceProvider>方法,該方法同樣返回它自己。如果我們調用它的GetService<IServiceScopeFactory>方法,它返回創建它的ServiceProviderEngine對象,也就是該方法和Engine屬性返回同一個對象。

依賴注入框架提供的服務實例最終是通過ServiceProviderEngine對象提供的。從上面給出的代碼片段可以看出,ServiceProviderEngine是一個抽象類,.NET Core依賴注入框架提供了如下四個具體的實現類型,默認使用的是DynamicServiceProviderEngine。

  • RuntimeServiceProviderEngine:採用反射的方式提供服務實例;
  • ILEmitServiceProviderEngine:採用IL Emit的方式提供服務實例;
  • ExpressionsServiceProviderEngine:採用表達式樹的方式提供服務實例;
  • DynamicServiceProviderEngine:根據請求併發數量動態決定最終的服務實例提供方案(反射和者IL Emit或者反射與表達式樹,是否選擇IL Emit取決於當前運行時是否支持Reflection Emit)。

4.4.2. ServiceProvider

調用IServiceCollection集合的擴展方法BuildServiceProvider創建的是一個ServiceProvider對象。作為根容器的ServiceProvider對象,和前面介紹的ServiceProviderEngine和ServiceProviderEngineScope對象,一起構建了整個依賴注入框架的設計藍圖。

在利用IServiceCollection集合創建ServiceProvider對象的時候,提供的服務註冊將用來創建一個具體的ServiceProviderEngine對象。該ServiceProviderEngine對象的RootScope就是它創建的一個ServiceProviderEngineScope對象,子容器提供的Singleton服務實例由它維護。如果調用ServiceProvider對象的GetService<IServiceProvider>方法,返回的其實不是它自己,而是作為RootScope的ServiceProviderEngineScope對象(調用ServiceProviderEngineScope對象的GetService<IServiceProvider>方法返回的是它自己)。

ServiceProvider和ServiceProviderEngineScope都實現了IServiceProvider接口,如果我們調用了它們的GetService<IServiceScopeFactory>方法,返回的都是同一個ServiceProviderEngine對象。這一個特性決定了調用它們的CreateScope擴展方法都會創建一個新的ServiceProviderEngineScope對象作為子容器。綜上所述,我們針對依賴注入框架總結出如下的特性:

  • ServiceProviderEngine的唯一性:整個服務提供體系只存在一個唯一的ServiceProviderEngine對象。
  • ServiceProviderEngine與IServiceFactory的同一性:唯一存在的ServiceProviderEngine會作為創建服務範圍的IServiceFactory工廠。
  • ServiceProviderEngineScope和IServiceProvider的同一性:表示服務範圍的ServiceProviderEngineScope同時也是作為服務提供者的依賴注入容器。

為了印證我們總結出來的特性,我們編寫的測試代碼。由於設計的ServiceProviderEngine和ServiceProviderEngineScope都是內部類型,我們只能採用反射的方式得到它們的屬性或者字段成員。上面總結的這些特徵體現在如下幾組調試斷言中。

class Program
{
    static void Main()
    {
        var (engineType, engineScopeType) = ResolveTypes();
        var root = new ServiceCollection().BuildServiceProvider();
        var child1 = root.CreateScope().ServiceProvider;
        var child2 = root.CreateScope().ServiceProvider;

        var engine = GetEngine(root);
        var rootScope = GetRootScope(engine, engineType);

        //ServiceProviderEngine的唯一性
        Debug.Assert(ReferenceEquals(GetEngine(rootScope, engineScopeType), engine));
        Debug.Assert(ReferenceEquals(GetEngine(child1, engineScopeType), engine));
        Debug.Assert(ReferenceEquals(GetEngine(child2, engineScopeType), engine));

        //ServiceProviderEngine和IServiceScopeFactory的同一性
        Debug.Assert(ReferenceEquals(root.GetRequiredService<IServiceScopeFactory>(), engine));
        Debug.Assert(ReferenceEquals(child1.GetRequiredService<IServiceScopeFactory>(), engine));
        Debug.Assert(ReferenceEquals(child2.GetRequiredService<IServiceScopeFactory>(), engine));

        //ServiceProviderEngineScope提供的IServiceProvider是它自己
        //ServiceProvider提供的IServiceProvider是RootScope
        Debug.Assert(ReferenceEquals(root.GetRequiredService<IServiceProvider>(), rootScope));
        Debug.Assert(ReferenceEquals(child1.GetRequiredService<IServiceProvider>(), child1));
        Debug.Assert(ReferenceEquals(child2.GetRequiredService<IServiceProvider>(), child2));

        //ServiceProviderEngineScope和IServiceProvider的同一性
        Debug.Assert(ReferenceEquals((rootScope).ServiceProvider, rootScope));
        Debug.Assert(ReferenceEquals(((IServiceScope)child1).ServiceProvider, child1));
        Debug.Assert(ReferenceEquals(((IServiceScope)child2).ServiceProvider, child2));
    }

    static (Type Engine, Type EngineScope) ResolveTypes()
    {
        var assembly = typeof(ServiceProvider).Assembly;
        var engine = assembly.GetTypes().Single(it => it.Name == "IServiceProviderEngine");
        var engineScope = assembly.GetTypes().Single(it => it.Name == "ServiceProviderEngineScope");
        return (engine, engineScope);
    }

    static object GetEngine(ServiceProvider serviceProvider)
    {
        var field = typeof(ServiceProvider).GetField("_engine", BindingFlags.Instance | BindingFlags.NonPublic);
        return field.GetValue(serviceProvider);
    }

    static object GetEngine(object enginScope, Type engineScopeType)
    {
        var property = engineScopeType.GetProperty("Engine", BindingFlags.Instance | BindingFlags.Public);
        return property.GetValue(enginScope);
    }

    static IServiceScope GetRootScope(object engine, Type engineType)
    {
        var property = engineType.GetProperty("RootScope", BindingFlags.Instance | BindingFlags.Public);
        return (IServiceScope)property.GetValue(engine);
    }
}

三、注入IServiceProvider對象

在《》中,我們從“Service Locator”設計模式是反模式的角度說明了為什麼不推薦在服務中注入IServiceProvider對象。不過反模式並不就等於是完全不能用的模式,有些情況下直接在服務構造函數中注入作為依賴注入容器的IServiceProvider對象可能是最快捷省事的解決方案。對於IServiceProvider對象的注入,有個細節大家可能忽略或者誤解。

讀者朋友們可以試着思考這麼一個問題:如果我們在某個服務中注入了IServiceProvider對象,當我們利用某個IServiceProvider對象來提供該服務實例的時候,注入的IServiceProvider對象是它自己嗎?以如下所示的代碼片段為例,我們定義了兩個在構造函數中注入了IServiceProvider對象的服務類型SingletonService和ScopedService,並按照命名所示的生命周期進行了註冊。

class Program
{
    static void Main()
    {
        var serviceProvider = new ServiceCollection()
            .AddSingleton<SingletonService>()
            .AddScoped<ScopedService>()
            .BuildServiceProvider();
        using (var scope = serviceProvider.CreateScope())
        {
            var child = scope.ServiceProvider;
            var singletonService = child.GetRequiredService<SingletonService>();
            var scopedService = child.GetRequiredService<ScopedService>();

            Debug.Assert(ReferenceEquals(child, scopedService.RequestServices));
            Debug.Assert(ReferenceEquals(rootScope, singletonService.ApplicationServices));
        }
    }            

    public class SingletonService
    {
        public IServiceProvider ApplicationServices { get; }
        public SingletonService(IServiceProvider serviceProvider) => ApplicationServices = serviceProvider;
    }

    public class ScopedService
    {
        public IServiceProvider RequestServices { get; }
        public ScopedService(IServiceProvider serviceProvider) => RequestServices = serviceProvider;
    }
}

我們最終利用一個作為子容器的IServiceProvider對象(ServiceProviderEngineScope對象)來提供這來個服務類型的實例,並通過調試斷言確定注入的IServiceProvider對象是否就是作為當前依賴注入容器的ServiceProviderEngineScope對象。如果在Debug模式下運行上述的測試代碼,我們會發現第一個斷言是成立的,第二個則不成立。

再次回到兩個服務類型的定義,SingletonService和ScopedService中通過注入IServiceProvider對象初始化的屬性分別被命名為ApplicationServices和RequestServices,意味着它們希望注入的分別是針對當前應用程序的根容器和針對請求的子容器。當我們利用針對請求的子容器來提供針對這兩個類型的服務實例時,如果注入的當前子容器的話,就與ApplicationServices的意圖不符。所以在提供服務實例的注入的IServiceProvider對象取決於採用的生命周期模式,具體策略為:

  • Singleton:注入的是ServiceProviderEngine的RootScope屬性表示的ServiceProviderEngineScope對象。
  • Scoped和Transient:如果當前IServiceProvider對象類型為ServiceProviderEngineScope,注入的就是它自己,如果是一個ServiceProvider對象,注入的還是ServiceProviderEngine的RootScope屬性表示的ServiceProviderEngineScope對象。

基於生命周期模式注入IServiceProvider對象的策略可以通過如下這個測試程序來驗證。最後還有一點需要補充一下:我們將調用IServiceCollection集合的BuildServiceProvider擴展方法創建的ServiceProvider對象作為根容器,它對應的ServiceProviderEngine對象的RootScope屬性返回作為根服務範圍的ServiceProviderEngineScope對象,ServiceProvider、ServiceProviderEngine和ServiceProviderEngineScope這三個類型全部實現了IServiceProvider接口,這三個對象都可以視為根容器。

class Program
{
    static void Main()
    {
        var serviceProvider = new ServiceCollection()
            .AddSingleton<SingletonService>()
            .AddScoped<ScopedService>()
            .BuildServiceProvider();
        var rootScope = serviceProvider.GetService<IServiceProvider>();
        using (var scope = serviceProvider.CreateScope())
        {
            var child = scope.ServiceProvider;
            var singletonService = child.GetRequiredService<SingletonService>();
            var scopedService = child.GetRequiredService<ScopedService>();

            Debug.Assert(ReferenceEquals(child, child.GetRequiredService<IServiceProvider>()));
            Debug.Assert(ReferenceEquals(child, scopedService.RequestServices));
            Debug.Assert(ReferenceEquals(rootScope, singletonService.ApplicationServices));
        }
    }
}

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享