Spring Boot 基本原理

一卖宠、內(nèi)容簡介

? 通過《Spring Boot 體驗(yàn)》介紹了Spring Boot 可以干什么旁理,這篇文章主要來解析它各個(gè)功能點(diǎn)的基本實(shí)現(xiàn)思路躏精,從而對Spring Boot有個(gè)整體的理性認(rèn)知卫枝。

  • 依賴管理:Spring Boot做了大量的starter惩系,而starter只是幫我們導(dǎo)入依賴項(xiàng)的一個(gè)入口刻诊,簡化項(xiàng)目依賴管理

  • 自動(dòng)配置:Spring Boot基于Spring代碼配置提供了很多常用組件和框架的配置類防楷,從而簡化項(xiàng)目配置

  • 內(nèi)嵌容器:集成Java的常見Web容器,簡化開發(fā)環(huán)境搭建则涯,而且是打包插件打包web應(yīng)用為可執(zhí)行文件的基礎(chǔ)

  • Maven插件:用于打包可直接運(yùn)行的jar文件或war文件复局,為項(xiàng)目的開箱即用提供支持冲簿,當(dāng)然還有輔助開發(fā)的一些小功能

  • 熱啟動(dòng):減少開發(fā)過程中反復(fù)啟動(dòng)容器的次數(shù),提高開發(fā)效率

  • 應(yīng)用監(jiān)控:為應(yīng)用審計(jì)亿昏、健康監(jiān)控峦剔、度量數(shù)據(jù)收集提供基本服務(wù)

  • CLI(命令行工具):進(jìn)行快速原型搭建,沒有必要使用

    ?

二龙优、起步依賴:starter

? 在常規(guī)的Maven工程中羊异,如果要使用某個(gè)框架或者組件,需要導(dǎo)入大量的依賴彤断,而且得注意依賴的版本匹配等問題野舶,在Spring Boot中提供了大量的starter,這樣的starter會借助Maven的依賴傳遞幫我們導(dǎo)入相關(guān)的依賴宰衙。比如以下的pom文件平道,它會添加web相關(guān)的依賴項(xiàng),包括Spring Web供炼、Spring MVC等:

    .......
    <dependencies>
        <!--Web應(yīng)用程序的典型依賴項(xiàng)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

    </dependencies>
    .......

原理:我們只是導(dǎo)入了一個(gè)依賴項(xiàng)<spring-boot-starter>一屋,但是該依賴項(xiàng)借助Maven的依賴傳遞幫我們導(dǎo)入了大量web開發(fā)要使用的包,如果解壓該依賴對應(yīng)的<spring-boot-starter-web-2.1.1.RELEASE.jar>文件袋哼,我們發(fā)現(xiàn)該jar文件中其實(shí)是沒有什么實(shí)質(zhì)性內(nèi)容的,因?yàn)樗皇且粋€(gè)pom項(xiàng)目冀墨,實(shí)質(zhì)性內(nèi)容在該包對應(yīng)的<spring-boot-starter-web-2.1.1.RELEASE.pom>文件中,該文件由mavne在下載jar文件時(shí)下載涛贯,在該文件中聲明了很多依賴項(xiàng)诽嘉,如:spring-webmvc、spring-web等弟翘。

簡而言之虫腋,我們的項(xiàng)目如果依賴了某個(gè)starter,那么該starter又會依賴很多其他依賴項(xiàng)稀余,而Maven的依賴傳遞會把starter依賴的依賴項(xiàng)添加到我們的項(xiàng)目中悦冀。starter只是做為了一個(gè)我們項(xiàng)目依賴項(xiàng)的導(dǎo)入中介。

有關(guān)maven的依賴傳遞可以參閱相關(guān)資料睛琳,簡單描述如下:

項(xiàng)目A依賴于B盒蟆,B又依賴于C。項(xiàng)目A只需要聲明依賴于B师骗,不需要聲明依賴于C茁影, Maven自動(dòng)管理這種依賴的傳遞。

二丧凤、自動(dòng)配置:AutoConfiguration

? Spring Boot會按照某些條件使用默認(rèn)值自動(dòng)配置相關(guān)的組件或框架募闲,從而大幅減少項(xiàng)目的配置文件,它在Spring自動(dòng)掃描和基于代碼配置的基礎(chǔ)上加入了自己的處理流程愿待。以下內(nèi)容先簡單介紹Spring基于代碼配置浩螺,然后介紹Spring Boot做了什么靴患。

(一)、Spring基于代碼配置

  1. 在Spring3以前要出,使用Spring上下文的方式一般是如下的:
  • Spring 配置文件

    <!-- 數(shù)據(jù)源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
     <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
     <property name="username" value="hr" />
     <property name="password" value="hr" />
    </bean>
    
    <!--組件掃描-->
    <context:component-scan base-package="com.demo.spring.sample.step03.?rvic?" />
    

    ?

  • 業(yè)務(wù)代碼

    package com.demo.spring.sample.step03.service.impl;
    .......
    @Service("userService")
    public class UserService implements IUserService {   
       @Autowired
       private IUserDAO userDAO = null;
    }
    

    ?

  • 創(chuàng)建Spring上下文

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    總結(jié):

? 通過component-scan告訴Spring去掃描類路徑下加入了@Component鸳君、 @Repository、@Service患蹂、 @Controlle注解的類或颊,Spring 實(shí)例化這些類,并且把實(shí)例注冊到Spring上下文中传于,但是數(shù)據(jù)源囱挑、屬性文件等第三方的bean還是采用XML文件來配置,如果要完全消除XML配置文件沼溜,還是不太可行的平挑,如果一定要做,相對比較麻煩系草。

? 使用 XML配置文件有利有弊通熄,其中一個(gè)弊端是無法過多的定制bean的實(shí)例化過程,比如以上的dataSource找都,如果想要在類路徑下有oracle的jdbc驅(qū)動(dòng)時(shí)才去實(shí)例化唇辨,這是無法完成的。還有一個(gè)弊端是代碼邏輯分散能耻,因?yàn)橛幸徊糠值倪壿嬍窃赬ML中配置的助泽;當(dāng)然好處就是配置集中化,而且方便配置切換嚎京。

  1. 在Spring3以后,可以通過如下的方式使用Spring容器:
  • Spring 配置類

    @Configuration // 表明當(dāng)前類提供Spring配置文件的作用隐解,Spring上下文會從當(dāng)前類的注解中提取配置信息
    @ComponentScan(basePackages = "com.demo.spring.sample.step08") // 開啟組件掃描
    public class AppConfig {
        @Bean // 表示這個(gè)方法實(shí)例化一個(gè)bean鞍帝,id=dataSource
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(userName);
            dataSource.setPassword(password);
            return dataSource;
        }
    }
    
  • 業(yè)務(wù)代碼

    package com.demo.spring.sample.step03.service.impl;
    .......
    @Service("userService")
    public class UserService implements IUserService {   
       @Autowired
       private IUserDAO userDAO = null;
    }
    
  • 創(chuàng)建Spring上下文

    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    

    總結(jié):

    ? 創(chuàng)建Spring上下文時(shí)不再使用基于XML的配置,配置文件消失煞茫,由AppConfig這個(gè)類來代替帕涌,這個(gè)類需要加@Configuration注解,而且該類中可以有加@Bean注解的方法续徽,容器會自動(dòng)調(diào)用這樣的方法來實(shí)例化Bean蚓曼。

    ?

(二)、Spring Boot的自動(dòng)配置

? Spring Boot幫寫了大量的加入了@Configuration注解的類钦扭,每個(gè)類提供一種組件或框架的配置纫版,比如DataSourceConfiguration.java中的靜態(tài)內(nèi)部類Dbcp2,它提供DBCP數(shù)據(jù)源的配置:

//DBCP 數(shù)據(jù)源配置.
@Configuration //這個(gè)注解在實(shí)際代碼中沒有加客情,當(dāng)前類被其它配置類Import
@ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type",  matchIfMissing = true,havingValue = "org.apache.commons.dbcp2.BasicDataSource")
static class Dbcp2 {

   @Bean
   @ConfigurationProperties(prefix = "spring.datasource.dbcp2")
   public org.apache.commons.dbcp2.BasicDataSource dataSource(
         DataSourceProperties properties) {
      return createDataSource(properties,
            org.apache.commons.dbcp2.BasicDataSource.class);
   }

}

總結(jié):

當(dāng)Spring Boot啟動(dòng)的基本步驟走完后其弊, 如果啟用了自動(dòng)配置癞己,Spring Boot會加載<spring-boot-autoconfigure-2.1.1.RELEASE.jar>下的<\META-INF\spring.factories>文件中的內(nèi)容,該文件中定義了有關(guān)自動(dòng)配置的信息梭伐,其中EnableAutoConfiguration對應(yīng)的每一個(gè)類中都加入了注解@Configuration痹雅,也就是說這樣的每一個(gè)類都相當(dāng)于Spring的一個(gè)或多個(gè)配置文件,而其中加注解@Bean的方法是bean的工廠方法,會由Spring上下文自動(dòng)調(diào)用糊识,并且將返回的對象注冊到上下文中绩社。

  • spring.factories文件中自動(dòng)配置類的部分內(nèi)容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
......
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
......

(三)、如何覆蓋自動(dòng)配置的屬性

? Spring Boot的自動(dòng)配置會采用大量的默認(rèn)值(約定由于配置)赂苗,可以通過在類路徑下提供application.properties或者application.yml配置文件來覆蓋默認(rèn)值愉耙,當(dāng)然部分屬性值必須通過該配置文件來提供哑梳,比如如果要使用Spring Boot對數(shù)據(jù)源的自動(dòng)配置劲阎,則在配置文件中必須提供jdbc的url,否則會拋出異常鸠真。

三悯仙、集成內(nèi)嵌容器 :main方法

? Spring Boot支持的內(nèi)嵌容器Tomcat、Jetty吠卷、Undertow本身就支持在Java中內(nèi)嵌使用锡垄,因?yàn)檫@些容器本身就是使用Java編寫的,只不過Spring Boot在main方法的調(diào)用鏈中根據(jù)自動(dòng)配置嵌入了這樣的容器祭隔。

不使用這樣的內(nèi)嵌容器也是可以的货岭,在Maven中移除這樣的依賴就可以,當(dāng)然這個(gè)時(shí)候如果要通過Spring Boot使用Web相關(guān)框架疾渴,則需要打包為war包后獨(dú)立部署千贯,或者在開發(fā)過程中使用IDE環(huán)境的開發(fā)部署功能。

? 不使用內(nèi)嵌容器的Web應(yīng)用在打包時(shí)需要對工程進(jìn)行一定的修改搞坝。

四搔谴、打包可運(yùn)行文件 :maven-plugin

? Maven使用的默認(rèn)打包工具支持打包jar文件或者war文件,但是打包后的jar文件中不能再嵌入jar文件桩撮,而打包后的war文件不能直接運(yùn)行敦第,為了把工程所有文件打包為一個(gè)可直接運(yùn)行的jar文件或war文件,spring提供了一個(gè)maven插件來解決這樣的問題店量。當(dāng)然這個(gè)插件還提諸如spring-boot:run這樣的開發(fā)功能

五芜果、熱啟動(dòng) :devtools

? 在開發(fā)過程中,當(dāng)完成一個(gè)功能單元后融师,我們會啟動(dòng)程序查看運(yùn)行效果右钾,如果代碼需要再次修改,則修改后需要關(guān)掉程序,然后重啟程序霹粥,這個(gè)過程不斷迭代灭将,從而完成代碼的編寫、調(diào)試后控。

? Spring Boot 熱啟動(dòng)通過重寫容器的類加載器庙曙,完成程序的部分重啟,從而簡化浩淘、加速程序的調(diào)試過程捌朴。spring-boot-devtools通過兩個(gè)類加載器分別加載依賴庫和項(xiàng)目代碼,當(dāng)spring-boot-devtools發(fā)現(xiàn)項(xiàng)目的編譯輸出路徑下有變化時(shí)张抄,通過其中的一個(gè)類加載器重新加載所有的項(xiàng)目自有代碼砂蔽,從而完成熱啟動(dòng)。這樣的熱啟動(dòng)比冷啟動(dòng)(關(guān)閉署惯、重啟)要快很多左驾,到底快多少取決于項(xiàng)目自有代碼的數(shù)量。

? 和熱啟動(dòng)對應(yīng)的還有一個(gè)熱替換极谊,是指單獨(dú)地替換被修改的某一個(gè)class到j(luò)vm中诡右,甚至可以單獨(dú)替換class的某個(gè)方法,這種方式比熱啟動(dòng)要快轻猖,通常使用 JavaAgent 攔截默認(rèn)加載器的行為來實(shí)現(xiàn)帆吻,spring有個(gè)獨(dú)立的項(xiàng)目Spring Loaded就是這么做的,但是項(xiàng)目已經(jīng)被移到了 attic 了咙边,也就是被Spring束之高閣猜煮,所以不建議使用。

六败许、應(yīng)用監(jiān)控:actuator

? 如果類路徑中有actuator這個(gè)組件的話王带,Spring Boot的自動(dòng)配置會自動(dòng)創(chuàng)建一些端點(diǎn)(端點(diǎn):遵循Restful設(shè)計(jì)風(fēng)格的資源,對應(yīng)于Controller的某一個(gè)處理請求的方法)市殷,這些端點(diǎn)接受請求后返回有關(guān)應(yīng)用的相關(guān)信息愕撰,比如:健康信息、線程信息等被丧。返回的是json格式的數(shù)據(jù),而使用 Spring Boot Admin 可以實(shí)現(xiàn)這些 JSON 數(shù)據(jù)的視圖展現(xiàn)绪妹,當(dāng)然也可以為其他應(yīng)用監(jiān)控系統(tǒng)監(jiān)控當(dāng)前系統(tǒng)提供服務(wù)甥桂。

七、問題:

  1. 為什么pom文件中要繼承spring-boot-starter-parent邮旷?

    spring-boot-starter-parent是spring-boot提供的一個(gè)pom黄选,在該pom中定義了很多屬性,比如:java源文件的字符編碼,編譯級別等办陷,還有依賴管理貌夕、資源定義的相關(guān)pom配置,項(xiàng)目的pom如果繼承starter-parent民镜,可以減少相關(guān)配置

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啡专,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子制圈,更是在濱河造成了極大的恐慌们童,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲸鹦,死亡現(xiàn)場離奇詭異慧库,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)馋嗜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門齐板,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人葛菇,你說我怎么就攤上這事甘磨。” “怎么了熟呛?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵宽档,是天一觀的道長。 經(jīng)常有香客問我庵朝,道長吗冤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任九府,我火速辦了婚禮椎瘟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侄旬。我一直安慰自己肺蔚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布儡羔。 她就那樣靜靜地躺著宣羊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汰蜘。 梳的紋絲不亂的頭發(fā)上仇冯,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音族操,去河邊找鬼苛坚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泼舱。 我是一名探鬼主播等缀,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼娇昙!你這毒婦竟也來了尺迂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤涯贞,失蹤者是張志新(化名)和其女友劉穎枪狂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宋渔,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡州疾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皇拣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片严蓖。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氧急,靈堂內(nèi)的尸體忽然破棺而出颗胡,到底是詐尸還是另有隱情,我是刑警寧澤吩坝,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布毒姨,位于F島的核電站,受9級特大地震影響钉寝,放射性物質(zhì)發(fā)生泄漏弧呐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一嵌纲、第九天 我趴在偏房一處隱蔽的房頂上張望俘枫。 院中可真熱鬧,春花似錦逮走、人聲如沸鸠蚪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茅信。三九已至,卻和暖如春墓臭,著一層夾襖步出監(jiān)牢的瞬間蘸鲸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工起便, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棚贾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓榆综,卻偏偏與公主長得像妙痹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子鼻疮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容