<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Tomcat源碼學(xué)習(xí)第2篇 - Bootstrap的初始化加載

          共 3922字,需瀏覽 8分鐘

           ·

          2021-03-24 09:31

          在上一篇中我們說到Tomcat的啟動入口是Bootstrap,那么今天我們就來研究一下,Bootstrap類在啟動main方法之后是如何進(jìn)行各項初始化來提供后續(xù)程序的運行的。

          1. Bootstrap.main()方法

          在main方法中我們可以看到,首先是創(chuàng)建了一個Bootstrap對象,并行初始化了一些相關(guān)的類加載器等操作,然后將創(chuàng)建的對象賦值給了 daemon,然后通過運行時附帶的參數(shù)來選擇它后續(xù)對應(yīng)的操作,這里我們直接看到 start 這里。(具體參數(shù)攜帶可以查看Tomcat項目的bin/startup.sh文件)

          c760493f157e07a37d201a21ffec9f35.webp
          public?static?void?main(String?args[])?{
          ?????//?實例化一個當(dāng)前Bootstrap引導(dǎo)類對象,并進(jìn)行類加載器的初始化,然后把該對象賦值給?daemon
          ????????synchronized?(daemonLock)?{
          ?????????...????
          ????????}

          ????????try?{
          ????????????String?command?=?"start";
          ????????????if?(args.length?>?0)?{
          ????????????????command?=?args[args.length?-?1];
          ????????????}
          ???//?執(zhí)行命令分支判斷
          ????????????if?(command.equals("startd"))?{
          ????????????????...
          ????????????}?else?if?(command.equals("stopd"))?{
          ????????????????...
          ????????????}?else?if?(command.equals("start"))?{???//?啟動?tomcat?時傳入的是?start?命令參數(shù),走此分支
          ????????????????daemon.setAwait(true);
          ????????????????//?加載初始化
          ????????????????daemon.load(args);
          ????????????????//?啟動
          ????????????????daemon.start();
          ????????????????if?(null?==?daemon.getServer())?{
          ????????????????????System.exit(1);
          ????????????????}
          ????????????}?else?if?(command.equals("stop"))?{
          ????????????????...
          ????????????}?else?if?(command.equals("configtest"))?{
          ????????????????...
          ????????????}?else?{
          ????????????????log.warn("Bootstrap:?command?\""?+?command?+?"\"?does?not?exist.");
          ????????????}
          ????????}?catch?(Throwable?t)?{
          ????????????...
          ????????}
          ????}

          2. Bootstrap.load()方法

          進(jìn)入load方法之后,我們可以看到它內(nèi)部實際是通過反射來調(diào)用 Catalina.load方法來進(jìn)行的初始化加載。0746061a489b816f36b781de3d4da74c.webp

          3. Catalina.load()方法

          在這個方法中,他會創(chuàng)建一個用于解析 XML 文件的對象 digester,然后通過 configFile方法得到conf/server.xml文件,并對其進(jìn)行解析,得到server對象(通過查看conf/server.xml文件,我們可以看到整個配置文件中,最外層的標(biāo)簽就是server,其內(nèi)部再一層層的嵌套其余的標(biāo)簽)。

          public?void?load()?{
          ????//?用于解析XML配置文件
          ????Digester?digester?=?createStartDigester();

          ????InputSource?inputSource?=?null;
          ????InputStream?inputStream?=?null;
          ????File?file?=?null;
          ????try?{
          ????????try?{
          ????????????//?定位到配置文件?server.xml
          ????????????file?=?configFile();
          ????????????inputStream?=?new?FileInputStream(file);
          ????????????inputSource?=?new?InputSource(file.toURI().toURL().toString());
          ????????}?catch?(Exception?e)?{
          ????????????...
          ????????}

          ????????try?{
          ????????????inputSource.setByteStream(inputStream);
          ????????????digester.push(this);
          ????????????//?調(diào)用?digester?對象真正的去解析?xml
          ????????????digester.parse(inputSource);
          ????????}?catch?(Exception?e)?{
          ????????????...
          ????????}
          ????????
          ????????try?{
          ????????????//?執(zhí)行server.init
          ????????????getServer().init();
          ????????}?catch?(LifecycleException?e)?{
          ????????????...
          ????????}
          ????}?finally?{
          ????????...
          ????}
          }

          4431259ff03bc7144481e8ff2220a3da.webp05fed9ac38f7ead828919b6e3ae1f4f8.webp

          拿到server對象之后,調(diào)用了一個 init方法,點擊該方法跳轉(zhuǎn)到對應(yīng)實現(xiàn)中722b3e5bed9897e5bf8d53e5a95baba4.webpaaf240678724690b6cd51a94f217fedb.webp

          4. LifecycleBase.initInternal()方法

          LifecycleBaseTomcat中組件生命周期的統(tǒng)一管理接口的實現(xiàn)類,該類對相關(guān)組件的生命周期進(jìn)行了統(tǒng)一管理,通過剛剛的跳轉(zhuǎn),我們找到了LifecycleBase.initInternal方法,該方法為抽象方法,需要再跳轉(zhuǎn)到對應(yīng)的子類中,這是一種典型設(shè)計模式《模板模式》,在父類中定義好了整體的步驟,具體的實現(xiàn)由子類自己去實現(xiàn)。68bf747aa5701628ffdbb0bc2ace6dbb.webp

          5. StandardServer.initInternal()方法

          DEBUG打上斷點,再按F7進(jìn)入方法內(nèi)部,來到StandardServer.initInternal處。

          這方法中有兩處地方調(diào)用了初始化方法:

          globalNamingResources.init()service.init(),分別對應(yīng)著配置文件中的兩處子標(biāo)簽,我們將重點放在service的初始化操作中,Tomcat中的連接器Connector與容器Engine都在這里。

          Tomcat中支持多個service的配置,所以此處需要遍歷進(jìn)行初始化操作。36aea3648499ed13df592463bcc0010f.webpdd2d67ba4a9ff0797dba1b5c71422aca.webp

          6. StandardService.initInternal()方法

          通過service.init方法,我們又回到了生命周期基礎(chǔ)類中,重新調(diào)用initInternal方法進(jìn)入對應(yīng)的StandardService類中,在該類的initInternal方法中我們可以看到有engineconnector的初始化操作。2006fb3ced122ae5b26cefb858edf097.webpc69f935f20d5b63422aa453d81cd464c.webp

          7. StandardEngine.initInternal()方法

          繼續(xù)套娃,進(jìn)入StandardEngine查看具體實現(xiàn)。在這里得到對應(yīng)的Realm,然后返回。d3e3d7b070c54e747cd4c73176d5981a.webp7c7691929aedd06a81806508c3fc83d6.webp

          8. Connector.initInternal()方法

          繼續(xù)往下走,來到connector.init()這里,初始化連接器組件。繼續(xù)往下走,看到了有針對protocolHandler.init()的一個初始化操作。c5a5df5d5a351310cc6c7fab14b64e04.webp8819a52daef839e14130baa358687e21.webp8f7fd3ed4d85365975fbc5563ed13c24.webp

          9. AbstractProtocol.init()方法

          先對endpoint對象進(jìn)行簡單的設(shè)置,然后再對其進(jìn)行初始化操作。7bde4ec24a94252021b74031d29e1de7.webp

          10. AbstractEndpoint.init()方法

          這里主要是做一個端口的綁定,具體的實現(xiàn)由NioEndpoint來進(jìn)行實現(xiàn)d7931838b0886d5a39afeb5a5458abf1.webp

          11. NioEndpoint.bind()方法

          在該方法中我們可以看到他創(chuàng)建了一個socket通道,綁定了我們在配置文件中設(shè)置的IP地址與端口。dfbef9ab1c6d922cbe61b38d8d757ecb.webp

          總結(jié)

          到此Bootstrap.load()方法中的初始化操作基本就完結(jié)了,我們在配置文件中設(shè)置的各個組件的參數(shù)均已進(jìn)行初始化。

          完整組件線路如下:

          Server
          ?Service
          ??Connector
          ?? EndPoint:通信端點(TCP/IP)
          ?? Processor:報文解析(HTTP/AJP)
          ?? Adapter:轉(zhuǎn)換器
          ??Container
          ???Catalina
          ??? Engine:引擎,是Servlet容器Catalina的核心,它支持在其下定義多個虛擬主機
          ??? Host:虛擬主機,允許Tomcat引擎在將配置在一臺機器上的多個域名分割開來互相不干擾
          ??? Context:上下文對象
          ??? Wrapper:包裝組件

          俄羅斯套娃:initInternal()68399b7e4e47c9a1e9f635055c605cba.webp

          我收集有眾多的 計算機電子書籍,有需要的小伙伴自提哦~

          - END -


          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产91白丝jk无套进入在线播放 | 日本一级 黄 色 片图片视频 | 国产精选久久久60086 | 色香蕉网| 97精品超碰一区二区三区 |