国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

這篇具有很好參考價值的文章主要介紹了手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


如果還沒有看第一篇文章的伙伴,建議先看第一篇文章 手寫自己的Springboot-1-整合tomcat,該文章在第一篇文章基礎(chǔ)上進行擴展.

在Springboot工程中怎樣對Servlet容器進行切換

在我們使用Springboot時,如果不想用Tomcat,想用Jetty,應(yīng)該怎么辦呢?
其實很簡單,我們只需要把Tomcat的依賴排除掉,然后引入Jetty即可.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

那Springboot底層究竟是怎樣處理的呢?

底層原理猜想,需要做哪些事情

首先要明確,Springboot的自動配置其實就是幫我們自動配置注入了很多bean, 比如原來的Spring需要整合Tomcat,一定需要配置一些Tomcat的bean, 需要整合Jetty,就一定需要配置一些Jetty相關(guān)的bean.

1.pom依賴

Springboot能夠啟動Jetty,能夠啟動tomcat,那它在自己內(nèi)部工程一定是同時引入這兩個依賴的.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置
那為什么使用者在切換的時候還需要額外引入Jetty的依賴呢?

其實這里利用了依賴的傳遞性,在Springboot內(nèi)部工程pom中,其實對于可選擇的依賴加上了<optional>true</optional>,加上該配置后,表示該依賴并不會傳遞,而tomcat依賴是沒有加該配置的,會進行依賴的傳遞.

如果不理解這部分的maven的知識,可以看一下這個文章Maven常見知識、沖突解決.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

所以,使用者默認是不需要額外引入Tomcat依賴的,而進行Jetty的切換時,需要額外引入Jetty的依賴.

那為什么要這么做呢?為什么不也直接讓使用者也都引入這些依賴呢?

對于使用者而言,比如說Servlet容器,其實一般最多都只用一個的,大部分都是Tomcat,那我就不需要引入其他的多余的依賴,那樣會使項目變得更加龐大, 還會極大增加依賴沖突的可能性.

2.判斷注入哪個bean

知道了怎么進行切換,那現(xiàn)在就應(yīng)該進行自動配置bean, 那怎么知道應(yīng)該注入哪個bean呢?是Tomcat的,還是Jetty的?

其實這里也非常簡單,就是通過判斷能不能加載到某一個類進行處理的.

比如說使用Tomcat,那我是一定有這個依賴,能夠加載到這個對象的.然后才把這個對象注入到Spring容器中.
也就是說配置這個bean是需要滿足一定的條件的.

具體代碼如下:
以下代碼就表示當加載到對應(yīng)的Tomcat,或 Jetty對象時, 才將對應(yīng)的bean注入到Spring容器中.
手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

@BlingConditionOnClass注解是模仿Springboot中的@ConditionOnClass注解自己定義的,他倆起到的效果是一樣的.都是加載到某一個類才生效.

@BlingConditionOnClass 這個注解其實底層最關(guān)鍵的其實是運用了Spring的原生注解@Conditional

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置
Conditional注解需要傳入一個實現(xiàn)Condition接口的實現(xiàn)類, 實現(xiàn)matches方法.

筆者這里是傳入了一個OnClassCondition類.在這個matches方法中就是做了一件事情,
就是判斷注解傳入的類路徑能不能被正常加載.

public class  OnClassCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
       //獲取BlingConditionOnClass注解中的所有屬性
        MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(BlingConditionOnClass.class.getName());
        //獲取其中的value屬性對應(yīng)的值
        List<Object> classPathList = attributes.get("value");
        if(classPathList == null || classPathList.isEmpty()){
            return false;
        }
        
        try {
            //加載傳入的類路徑
            Objects.requireNonNull(context.getClassLoader()).loadClass((String) classPathList.get(0));
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

總體思路是這樣的:

  1. 當Spring掃描加載到WebServerAutoConfigration這個類的時候.會解析類上的注解.該類上標識了@Configuration注解.Spring就會解析調(diào)用這個類中標識了@Bean的方法.
  2. 當解析到tomcatWebServer()方法時,則通過反射可以解析到該方法上的注解@BlingConditionOnClass(“org.apache.catalina.startup.Tomcat”),并記錄傳入注解的值org.apache.catalina.startup.Tomcat
  3. 然后會解析到@BlingConditionOnClass注解中的注解@Conditional(OnClassCondition.class)
  4. 接下來會調(diào)用Condition接口實現(xiàn)類OnClassCondition的matches方法,根據(jù)方法該方法的返回值判斷是否將該對象注入到Spring容器中.

根據(jù)以上流程就可以達到引入不同maven依賴而自動注入不同bean的效果.

3.讓使用者能夠加載到自動配置類

目前問題及通用處理方式

現(xiàn)在看起來好像是已經(jīng)能達到我們剛開始想要的效果了, 通過引入不同的maven依賴向Spring容器注入不同的bean,但是還有一個很關(guān)鍵的點.

就是當使用者引入該項目,他怎么能夠掃描加載到項目中WebServerAutoConfigration這個自動配置類呢?

我們知道Spring會默認掃描傳入啟動類所在的包路徑.比如說下面這個工程,傳入的是TestApplication, 這個類所在的包路徑是com.bling.test,那么Spring就會掃描加載這個路徑下所有的類.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

而我們自己的寫的Springboot項目需要加載的自動配置類,在com.bling.springboot路徑下.默認當然是不會掃描加載到的.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

此時,最常見的有兩種方法,可以從使用者的角度去加載的這個自動配置類 :

  1. 使用Import注解.直接導(dǎo)入
    手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置
  2. 指定掃描路徑,從而去掃描加載對應(yīng)的類.
    手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置
    那Springboot真實是怎樣做的呢? 以上兩種方法都沒有采用, 因為在我們的工程中可能會導(dǎo)入很多的依賴, 有很多很多的自動配置類,也有很多很多不同的項目路徑, 難道我們要把這些配置類和路徑全都寫一遍嗎? 這是非常不方便的.
真實Springboot處理方式

真實Spring在進行處理的時候會在@SpringBootApplication注解上Import一個類,AutoConfigurationImportSelector, 見名知義,也就是自動配置導(dǎo)入選擇器. 這里也模仿Springboot這樣處理.
手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

這個類實現(xiàn)了ImportSelector接口,重寫了selectImports方法,這個方法要返回什么呢?
其實就是返回需要被Spring掃描管理的類的全類名.返回的類將會被Spring容器加載管理.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

那在這個方法中又應(yīng)該怎樣獲取到所有自動配置類的全類名呢?

這里Spring利用的是SPI機制,SPI (Service Provider Interface)本身是一個概念,有很多的框架會去實現(xiàn)自己的SPI.比如Spring,它自己實現(xiàn)加載的spring.factories, 就是SPI機制, 當然JDK本身也有實現(xiàn)的一套SPI的機制.

我們這里就不去實現(xiàn)Spring的這一套SPI,比較麻煩,我們這里直接使用JDK的SPI進行演示處理.核心理解為什么要在這里用到SPI就行.

使用JDK SPI機制步驟:
首先明確JDK SPI是針對接口進行處理的,就是當你傳入一個接口, 它可以獲取這個接口對應(yīng)的所有配置的實現(xiàn)類.

  1. 所以先定義一個AutoConfigration接口.讓WebServerAutoConfigration去實現(xiàn)它.
    手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

  2. 在resources目錄下新建文件夾META-INF,在該文件夾下再新建文件夾services.在services下新建一個文件,文件名就是接口全類名.
    在該文件中配置好對應(yīng)的實現(xiàn)類.
    手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

  3. 使用JDK中的ServiceLoader類進行加載.

/**
 * @ClassName:     
 * @Description: 該類標識在啟動類中,使用Import注解導(dǎo)入,所以Spring會對該類進行加載
 * @author: 
 * @date:        
 *   
 */
public class AutoConfigurationImportSelector implements ImportSelector {
    /**
     * @param importingClassMetadata
     * @return 返回需要加載到Spring容器的全類名
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //這里暫時不引入Spring中的SPI,比較復(fù)雜
        //直接使用Java中的SPI
        ArrayList<String> result = new ArrayList<>();
        ServiceLoader<AutoConfigration> load = ServiceLoader.load(AutoConfigration.class);
        for (AutoConfigration autoConfigration : load) {
            result.add(autoConfigration.getClass().getName());
        }
        return result.toArray(new String[0]);
    }
}

至此,就完完全全的能夠達到我們在最開始提到的想法,想切換不同的Servlet容器,直接切換maven依賴就可以.

進行測試

想看該項目完整代碼的可以到Github上下載:手寫自己的springboot
如果有網(wǎng)絡(luò)不通的小伙伴也可以到CSDN中下載CSDN地址下載.

我們還是將該項目進行打包, 額外新建一個非常簡單的maven項目,引入該項目依賴,如下:

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

可以正常啟動tomcat…

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

然后,排除Tomcat依賴,加入Jetty依賴.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

現(xiàn)在就可以啟動Jetty.

手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置

關(guān)鍵點總結(jié)

整個流程下來,其實主要有三點:

  1. springboot本身是引入所有組件依賴的,只不過利用maven依賴的傳遞性, 讓使用者不需要引入額外的依賴
  2. 關(guān)于自動配置bean,其實大量運用了條件注解, 通過一定的條件判斷該bean是否需要注入到Spring容器
  3. 為了讓使用者能夠較為方便的加載到自動配置類, 使用了SPI技術(shù)進行處理.

今天的分享就到這里了,有問題可以在評論區(qū)留言,均會及時回復(fù)呀.
我是bling,未來不會太差,只要我們不要太懶就行, 咱們下期見.
手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置文章來源地址http://www.zghlxwxcb.cn/news/detail-452076.html

到了這里,關(guān)于手寫自己的Springboot-2-從Servlet容器選擇徹底理解自動配置的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Kubernetes VS Docker Swarm:選擇適合自己的容器編排工具

    容器編排工具是一種自動化部署和管理容器的工具。 利用容器編排工具可以方便地解決容器化應(yīng)用程序的部署、擴展和高可用性等問題。 Kubernetes 和 Docker Swarm 是目前最流行的兩個容器編排工具,因此選用它們來進行比較。 1.1 Kubernetes 的來源和發(fā)展背景 Kubernetes 源于 Google 的

    2024年02月06日
    瀏覽(16)
  • 終于可以徹底告別手寫正則表達式了

    終于可以徹底告別手寫正則表達式了

    這篇文章的目的是讓你能得到完美的正則表達式,而且還不用自己拼。 說到正則表達式,一直是令我頭疼的問題,這家伙一般時候用不到,等用到的時候發(fā)現(xiàn)它的規(guī)則是一點兒也記不住, d 表示一個數(shù)字, s 表示包括下劃線在內(nèi)的任意單詞字符,也就是 [A-Za-z0-9_] ,還有

    2024年02月15日
    瀏覽(23)
  • Linux小程序: 手寫自己的shell

    注意: 本文章只是為了理解shell內(nèi)部的工作原理, 所以并沒有完成shell的所有工作, 只是完成了shell里的一小部分工作

    2024年04月09日
    瀏覽(16)
  • 深度學習(六):paddleOCR理解及識別手寫體,手寫公式,表格

    深度學習(六):paddleOCR理解及識別手寫體,手寫公式,表格

    光學字符識別(Optical Character Recognition, OCR),ORC是指對包含文本資料的圖像文件進行分析識別處理,獲取文字及版面信息的技術(shù),檢測圖像中的文本資料,并且識別出文本的內(nèi)容。 那么有哪些應(yīng)用場景呢? 其實我們?nèi)粘I钪刑幪幎加衞cr的影子,比如在疫情期間身份證識別

    2024年02月05日
    瀏覽(39)
  • Servlet容器中的會話管理設(shè)計說明

    Servlet容器是一種用于運行Java Servlet的容器,它是Web服務(wù)器的一部分。它負責處理Servlet的生命周期、請求和響應(yīng)處理、多線程處理、會話管理等任務(wù)。 以下是Servlet容器架構(gòu)的主要設(shè)計說明: Servlet容器架構(gòu)通常是基于分層結(jié)構(gòu)設(shè)計的。最底層是網(wǎng)絡(luò)層,負責接收和發(fā)送請求和

    2024年02月15日
    瀏覽(16)
  • 【Spring專題】手寫簡易Spring容器過程分析

    【Spring專題】手寫簡易Spring容器過程分析

    首先必須得聲明的是,下面的流程并不代表Spring源碼中真正的流程。而是,我們通過現(xiàn)在的Spring提供給我們的某些基礎(chǔ)功能,反推過來的流程。所以,并不全面,但是會具有一點參考性。 由于Spring源碼分析是一個前后聯(lián)系比較強的過程,而且這邊分析,也是按照代碼順序講解

    2024年02月13日
    瀏覽(37)
  • 徹底理解solidity中的事件

    在我之前的幾篇關(guān)于智能合約的文章中,都有提到事件的用法,比如: 這里定義了兩個事件,分別表示最高競價更新了和拍賣結(jié)束了。 然后在需要的位置,調(diào)用事件,比如: 我們可以通過emit調(diào)用事件方法,然后這個事件就作為日志記錄到了以太坊區(qū)塊鏈中。日志是以太坊區(qū)

    2024年02月02日
    瀏覽(18)
  • 【框架源碼】手寫Spring框架IOC容器核心流程

    【框架源碼】手寫Spring框架IOC容器核心流程

    要是想要了解Spring IOC底層,首先我們就得先了解什么是IOC。 IOC就是控制反轉(zhuǎn),把對象創(chuàng)建和對象之間的調(diào)用過程交給Spring進行管理。 使用IOC目的就是之前我們創(chuàng)建對象的方式都是用new的方式創(chuàng)建,這個方式有個缺點,被創(chuàng)建對象的類的位置一旦被改動,new就會報錯,類與類

    2024年02月06日
    瀏覽(27)
  • 選擇什么電容筆比較好?平板手寫筆推薦

    選擇什么電容筆比較好?平板手寫筆推薦

    由于蘋果Pencil的熱銷,讓華國內(nèi)市場上,也出現(xiàn)了不少的平替式電容筆,這些產(chǎn)品,有好有壞,價格也很公道。不過,也有很多產(chǎn)品的價格都很平價。我是一個擁有多年經(jīng)驗的數(shù)碼發(fā)燒友,在前幾年就開始用上了電容筆,因此我對電容筆的了解并不少,所以在這里給各位推薦

    2024年02月06日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包