
來源 | 純潔的微笑
聲明:本媒體文章轉載,版權歸原作者所有
Spring Boot方式的項目開發已經逐漸成為Java應用開發領域的主流架構,它不僅可以友善地建立生産級的Spring應用程式,還能輕松地通過一些注解配置與目前比較流行的微服務架構SpringCloud快速地內建。
在我們實際使用Spring Boot進行項目開發的過程中,往往隻需要幾個很簡單的注解配置就能夠将應用啟動運作了,相比于傳統的Spring項目而已,這種提升大大地提高了我們的研發效率。然而,這種便捷性則是通過高度地上層封裝來實作的,如:“大量的注解封裝、約定大于配置的原則“等手段。是以,也許你已經使用Spring Boot開發很多個項目了,但對Spring Boot的運作原理真的搞清楚了嗎?如果,面試中有人問你Spring Boot的實作原理是什麼?你能正确地回答出來嗎?
與大部分其他架構及技術的使用場景一樣,我們往往過多地專注于使用層面,以便快速地完成業務開發,卻往往忽略了對架構底層運作原理的關注,是以面試中被怼也就不足為奇了。不過沒關系,在今天的文章中,小碼哥将為大家全方位地梳理下Spring Boot的底層運作原理,并通過圖文結合的方式給大家進行展示,希望對您的工作或者面試能夠有所幫助!
Spring Boot運作原理
實際上Spring Boot并不是要替代Spring架構,我們知道在JDK1.5推出注解功能以後,Spring架構實作了大量的注解來替代原有的基于XML的配置,主要用于配置管理、Bean的注入以及AOP等相關功能的實作。然而,随着Spring注解的數量越來越多,并且被大量的使用,尤其是相同的多個注解會被大量重複地用到各個類或者方法中。這樣就導緻了繁瑣的配置及大量備援的代碼。
到這裡你也許就會想到既然這麼多Spring注解很繁瑣,那麼可不可以将其組合一下呢?通過定義一些新的注解,将功能進行分類,不同的Spring注解通過新的注解定義進行一定的組合,這樣對于大部分通用場景下,隻需要引入一個新的注解,就自動包含了與之相關的其他Spring注解?沒錯!Spring Boot說到底就是這麼個玩意!
但是,要實作注解的組合并不是簡單的把多個注解牽強的疊加在一起,這裡涉及到一些程式設計語言上的實作,例如要組合一個注解,那麼該注解是否支援注解到别的注解上呢(略微有點拗口)?還有如果組合注解後,因為注解的背後還涉及到Spring容器上下文的初始化以及Bean注入相關的邏輯,如果一個A注解涉及的Bean,涉及到另外一個B注解涉及到的Bean的初始化;也就意味着A注解的Bean初始化,需要在B注解的Bean初始化完成後才能進行注入,否則就會導緻Bean依賴注入的失敗。
Spring Boot架構本質上就是通過組合注解的方式實作了諸多Spring注解的組合,進而極大地簡化了Spring架構本身的繁瑣配置,實作快速的內建和開發。隻是要這樣實作,也需要一定的基礎條件!
元注解
說到底Spring Boot架構是在Spring架構的基礎上做了一層二次封裝,最重要的特點就是Spring Boot架構定義了一些新的注解來實行一些Spring注解的組合,而Spring注解則是基于JDK1.5+後的注解功能的支援來完成的。
關于JDK的注解如果想要注解到别的注解上,就需要将其定義為元注解,所謂的元注解,就是可以注解到其他注解上的注解,被注解的注解就是我們上面說到的組合注解。而Spring架構的很多注解都是可以作為元注解的,并且Spring架構本身也實作了很多組合注解,例如我們常用的@Configuration就是一個這樣的組合注解。是以,有了這樣一個條件Spring Boot的實作才有了基礎條件!
條件注解@Conditional
Spring 4提供了一個通用的基于條件的注解@Conditional。該注解可以根據滿足某一個特定條件與否來決定是否建立某個特定的Bean,例如,某個依賴包jar在一個類路徑的時候,自動配置一個或多個Bean時,可以通過@Conditional注解來實作隻有某個Bean被建立時才會建立另外一個Bean,這樣就可以依據特定的條件來控制Bean的建立行為,這樣的話我們就可以利用這樣一個特性來實作一些自動的配置。
而這一點對于Spring Boot實作自動配置來說是一個核心的基礎能力,從本質上來說Spring Boot之是以可以實作自動注解配置很大程度上也是基于這一能力。在Spring Boot中以@Conditional為元注解又重新定義了一組針對不同場景的組合條件注解,它們分别是:
@ConditionalOnBean:當容器中有指定Bean的條件下進行執行個體化。
@ConditionalOnMissingBean:當容器裡沒有指定Bean的條件下進行執行個體化。
@ConditionalOnClass:當classpath類路徑下有指定類的條件下進行執行個體化。
@ConditionalOnMissingClass:當類路徑下沒有指定類的條件下進行執行個體化。
@ConditionalOnWebApplication:當項目是一個Web項目時進行執行個體化。
@ConditionalOnNotWebApplication:當項目不是一個Web項目時進行執行個體化。
@ConditionalOnProperty:當指定的屬性有指定的值時進行執行個體化。
@ConditionalOnExpression:基于SpEL表達式的條件判斷。
縱觀Spring Boot的一些核心注解,基于@Conditional元注解的組合注解就占了很大部分,是以Spring Boot的核心功能基于就是這些注解實作的。在Spring Boot源碼項目“spring-boot-autoconfigure”中,随意打開一個AutoConfiguration檔案,我們都會看到有上述條件注解的使用。如:
在前面的篇幅中我們重點闡述了為什麼Spring Boot可以實作高度地自動化配置。那麼,接下來我們就結合Spring Boot最核心的組合注解@SpringBootApplication來分析下Spring Boot的項目到底是怎麼啟動運作的。
@SpringBootApplication注解實際上是一個組合注解,除了對應用開放的@ComponentScan注解(實作對開發者自定義的應用包掃描)外,其最核心的注解就是@EnableAutoConfiguration,該注解表示開啟自動配置功能,而在具體的實作上則是通過導入@Import(EnableAutoConfigurationImportSelector.class)類的執行個體,在邏輯上實作了對所依賴的核心jar下META-INF/spring.factories檔案的掃描,該檔案則聲明了有哪些自動配置需要被Spring容器加載,進而Spring Boot應用程式就能自動加載Spring核心容器配置,以及其他依賴的項目元件配置,進而最終完成應用的自動初始化,通過這種方法就向開發者屏蔽了啟動加載的過程。
如“spring-boot-autoconfigure”核心包中的META-INF/spring.factories檔案就是定義了需要加載的Spring Boot項目所依賴的基礎配置類,如Spring的容器初始化配置類等。如:
而對于大部分第三方需要與Spring Boot內建的架構,或者我們日常開發中需要進行抽象的公共元件而言,得益于這種機制,也可以很容易地定制成開箱即用的各種Starter元件。而使用這些元件的使用者,往往隻需要将依賴引入就好,不再需要進行任何額外的配置了!
Spring Boot後記
以上就是Spring Boot運作的基本原理了,希望這篇文章能夠對你有所幫助!實際上學習Spring Boot進行項目開發關鍵就是要掌握各種Spring及Spring Boot的各種注解,特别是一些關鍵核心注解。同樣在進行基于Spring Cloud微服務的開發中,也是需要了解Spring Cloud相關元件所提供的各種核心注解,隻有這樣才能更好的了解架構的原理及使用,而不隻是雲裡霧裡地進行各種似懂非懂的Copy開發。