溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring Boot的運(yùn)行原理是什么

發(fā)布時(shí)間:2021-08-26 16:06:49 來(lái)源:億速云 閱讀:155 作者:chen 欄目:編程語(yǔ)言

本篇內(nèi)容介紹了“Spring Boot的運(yùn)行原理是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

導(dǎo)讀

Spring Boot方式的項(xiàng)目開(kāi)發(fā)已經(jīng)逐步成為Java應(yīng)用開(kāi)發(fā)領(lǐng)域的主流框架,它不僅可以方便地創(chuàng)建生產(chǎn)級(jí)的Spring應(yīng)用程序,還能輕松地通過(guò)一些注解配置與目前比較流行的微服務(wù)框架SpringCloud快速地集成。

在我們實(shí)際使用Spring Boot進(jìn)行項(xiàng)目開(kāi)發(fā)的過(guò)程中,往往只需要幾個(gè)很簡(jiǎn)單的注解配置就能夠?qū)?yīng)用啟動(dòng)運(yùn)行了,相比于傳統(tǒng)的Spring項(xiàng)目而已,這種提升大大地提高了我們的研發(fā)效率。然而,這種便捷性則是通過(guò)高度地上層封裝來(lái)實(shí)現(xiàn)的,如:“大量的注解封裝、約定大于配置的原則“等手段。所以,也許你已經(jīng)使用Spring Boot開(kāi)發(fā)很多個(gè)項(xiàng)目了,但對(duì)Spring Boot的運(yùn)行原理真的搞清楚了嗎?如果,面試中有人問(wèn)你Spring Boot的實(shí)現(xiàn)原理是什么?你能正確地回答出來(lái)嗎?

與大部分其他框架及技術(shù)的使用場(chǎng)景一樣,我們往往過(guò)多地專注于使用層面,以便快速地完成業(yè)務(wù)開(kāi)發(fā),卻往往忽略了對(duì)框架底層運(yùn)行原理的關(guān)注,所以面試中被懟也就不足為奇了。不過(guò)沒(méi)關(guān)系,在今天的文章中,小碼哥將為大家全方位地梳理下Spring Boot的底層運(yùn)行原理,并通過(guò)圖文結(jié)合的方式給大家進(jìn)行展示,希望對(duì)您的工作或者面試能夠有所幫助!

Spring Boot運(yùn)行原理

實(shí)際上Spring Boot并不是要替代Spring框架,我們知道在JDK1.5推出注解功能以后,Spring框架實(shí)現(xiàn)了大量的注解來(lái)替代原有的基于XML的配置,主要用于配置管理、Bean的注入以及AOP等相關(guān)功能的實(shí)現(xiàn)。然而,隨著Spring注解的數(shù)量越來(lái)越多,并且被大量的使用,尤其是相同的多個(gè)注解會(huì)被大量重復(fù)地用到各個(gè)類或者方法中。這樣就導(dǎo)致了繁瑣的配置及大量冗余的代碼。

到這里你也許就會(huì)想到既然這么多Spring注解很繁瑣,那么可不可以將其組合一下呢?通過(guò)定義一些新的注解,將功能進(jìn)行分類,不同的Spring注解通過(guò)新的注解定義進(jìn)行一定的組合,這樣對(duì)于大部分通用場(chǎng)景下,只需要引入一個(gè)新的注解,就自動(dòng)包含了與之相關(guān)的其他Spring注解?沒(méi)錯(cuò)!Spring Boot說(shuō)到底就是這么個(gè)玩意!

但是,要實(shí)現(xiàn)注解的組合并不是簡(jiǎn)單的把多個(gè)注解牽強(qiáng)的疊加在一起,這里涉及到一些編程語(yǔ)言上的實(shí)現(xiàn),例如要組合一個(gè)注解,那么該注解是否支持注解到別的注解上呢(略微有點(diǎn)拗口)?還有如果組合注解后,因?yàn)樽⒔獾谋澈筮€涉及到Spring容器上下文的初始化以及Bean注入相關(guān)的邏輯,如果一個(gè)A注解涉及的Bean,涉及到另外一個(gè)B注解涉及到的Bean的初始化;也就意味著A注解的Bean初始化,需要在B注解的Bean初始化完成后才能進(jìn)行注入,否則就會(huì)導(dǎo)致Bean依賴注入的失敗。

Spring Boot框架本質(zhì)上就是通過(guò)組合注解的方式實(shí)現(xiàn)了諸多Spring注解的組合,從而極大地簡(jiǎn)化了Spring框架本身的繁瑣配置,實(shí)現(xiàn)快速的集成和開(kāi)發(fā)。只是要這樣實(shí)現(xiàn),也需要一定的基礎(chǔ)條件!

元注解

說(shuō)到底Spring Boot框架是在Spring框架的基礎(chǔ)上做了一層二次封裝,最重要的特點(diǎn)就是Spring Boot框架定義了一些新的注解來(lái)實(shí)行一些Spring注解的組合,而Spring注解則是基于JDK1.5+后的注解功能的支持來(lái)完成的。

關(guān)于JDK的注解如果想要注解到別的注解上,就需要將其定義為元注解,所謂的元注解,就是可以注解到其他注解上的注解,被注解的注解就是我們上面說(shuō)到的組合注解。而Spring框架的很多注解都是可以作為元注解的,并且Spring框架本身也實(shí)現(xiàn)了很多組合注解,例如我們常用的@Configuration就是一個(gè)這樣的組合注解。因此,有了這樣一個(gè)條件Spring Boot的實(shí)現(xiàn)才有了基礎(chǔ)條件!

條件注解@Conditional

Spring 4提供了一個(gè)通用的基于條件的注解@Conditional。該注解可以根據(jù)滿足某一個(gè)特定條件與否來(lái)決定是否創(chuàng)建某個(gè)特定的Bean,例如,某個(gè)依賴包jar在一個(gè)類路徑的時(shí)候,自動(dòng)配置一個(gè)或多個(gè)Bean時(shí),可以通過(guò)@Conditional注解來(lái)實(shí)現(xiàn)只有某個(gè)Bean被創(chuàng)建時(shí)才會(huì)創(chuàng)建另外一個(gè)Bean,這樣就可以依據(jù)特定的條件來(lái)控制Bean的創(chuàng)建行為,這樣的話我們就可以利用這樣一個(gè)特性來(lái)實(shí)現(xiàn)一些自動(dòng)的配置。

這一點(diǎn)對(duì)于Spring Boot實(shí)現(xiàn)自動(dòng)配置來(lái)說(shuō)是一個(gè)核心的基礎(chǔ)能力,從本質(zhì)上來(lái)說(shuō)Spring Boot之所以可以實(shí)現(xiàn)自動(dòng)注解配置很大程度上也是基于這一能力。在Spring Boot中以@Conditional為元注解又重新定義了一組針對(duì)不同場(chǎng)景的組合條件注解,它們分別是:

  • @ConditionalOnBean:當(dāng)容器中有指定Bean的條件下進(jìn)行實(shí)例化。

  • @ConditionalOnMissingBean:當(dāng)容器里沒(méi)有指定Bean的條件下進(jìn)行實(shí)例化。

  • @ConditionalOnClass:當(dāng)classpath類路徑下有指定類的條件下進(jìn)行實(shí)例化。

  • @ConditionalOnMissingClass:當(dāng)類路徑下沒(méi)有指定類的條件下進(jìn)行實(shí)例化。

  • @ConditionalOnWebApplication:當(dāng)項(xiàng)目是一個(gè)Web項(xiàng)目時(shí)進(jìn)行實(shí)例化。

  • @ConditionalOnNotWebApplication:當(dāng)項(xiàng)目不是一個(gè)Web項(xiàng)目時(shí)進(jìn)行實(shí)例化。

  • @ConditionalOnProperty:當(dāng)指定的屬性有指定的值時(shí)進(jìn)行實(shí)例化。

  • @ConditionalOnExpression:基于SpEL表達(dá)式的條件判斷。

  • @ConditionalOnJava:當(dāng)JVM版本為指定的版本范圍時(shí)觸發(fā)實(shí)例化。

  • @ConditionalOnResource:當(dāng)類路徑下有指定的資源時(shí)觸發(fā)實(shí)例化。

  • @ConditionalOnJndi:在JNDI存在的條件下觸發(fā)實(shí)例化。

  • @ConditionalOnSingleCandidate:當(dāng)指定的Bean在容器中只有一個(gè),或者有多個(gè)但是指定了首選的Bean時(shí)觸發(fā)實(shí)例化。

縱觀Spring Boot的一些核心注解,基于@Conditional元注解的組合注解就占了很大部分,所以Spring Boot的核心功能基于就是這些注解實(shí)現(xiàn)的。在Spring Boot源碼項(xiàng)目“spring-boot-autoconfigure”中,隨意打開(kāi)一個(gè)AutoConfiguration文件,我們都會(huì)看到有上述條件注解的使用。如:

@Configuration
@ConditionalOnClass(DSLContext.class)
@ConditionalOnBean(DataSource.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
        TransactionAutoConfiguration.class })
public class JooqAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DataSourceConnectionProvider dataSourceConnectionProvider(
            DataSource dataSource) {
        return new DataSourceConnectionProvider(
                new TransactionAwareDataSourceProxy(dataSource));
    }

    @Bean
    @ConditionalOnBean(PlatformTransactionManager.class)
    public SpringTransactionProvider transactionProvider(
            PlatformTransactionManager txManager) {
        return new SpringTransactionProvider(txManager);
    }
    ....
}

Spring Boot運(yùn)行原理

在前面的篇幅中我們重點(diǎn)闡述了為什么Spring Boot可以實(shí)現(xiàn)高度地自動(dòng)化配置。那么,接下來(lái)我們就結(jié)合Spring Boot最核心的組合注解@SpringBootApplication來(lái)分析下Spring Boot的項(xiàng)目到底是怎么啟動(dòng)運(yùn)行的。

Spring Boot的運(yùn)行原理是什么

@SpringBootApplication注解實(shí)際上是一個(gè)組合注解,除了對(duì)應(yīng)用開(kāi)放的@ComponentScan注解(實(shí)現(xiàn)對(duì)開(kāi)發(fā)者自定義的應(yīng)用包掃描)外,其最核心的注解就是@EnableAutoConfiguration,該注解表示開(kāi)啟自動(dòng)配置功能,而在具體的實(shí)現(xiàn)上則是通過(guò)導(dǎo)入@Import(EnableAutoConfigurationImportSelector.class)類的實(shí)例,在邏輯上實(shí)現(xiàn)了對(duì)所依賴的核心jar下META-INF/spring.factories文件的掃描,該文件則聲明了有哪些自動(dòng)配置需要被Spring容器加載,從而Spring Boot應(yīng)用程序就能自動(dòng)加載Spring核心容器配置,以及其他依賴的項(xiàng)目組件配置,從而最終完成應(yīng)用的自動(dòng)初始化,通過(guò)這種方法就向開(kāi)發(fā)者屏蔽了啟動(dòng)加載的過(guò)程。

如“spring-boot-autoconfigure”核心包中的META-INF/spring.factories文件就是定義了需要加載的Spring Boot項(xiàng)目所依賴的基礎(chǔ)配置類,如Spring的容器初始化配置類等。如:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

.....

而對(duì)于大部分第三方需要與Spring Boot集成的框架,或者我們?nèi)粘i_(kāi)發(fā)中需要進(jìn)行抽象的公共組件而言,得益于這種機(jī)制,也可以很容易地定制成開(kāi)箱即用的各種Starter組件。而使用這些組件的用戶,往往只需要將依賴引入就好,不再需要進(jìn)行任何額外的配置了!

“Spring Boot的運(yùn)行原理是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI