spring-boot-starters模塊包含了SpringBoot內(nèi)置的各種starter:spring-boot-starter-xxx。由于SpringBoot內(nèi)置的各種starter太多,以我們常用的spring-boot-starter-web起步依賴來探究。
看下spring-boot-starter-web模塊的pom.xml文件內(nèi)容:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
可以看到,spring-boot-starter-web模塊依賴了spring-boot-starter,spring-boot-starter-tomcat,spring-web和spring-webmvc等模塊,居然沒有依賴spring-boot-autoconfigure自動配置模塊!
由于spring-boot-starter-web模塊肯定跟spring-boot-autoconfigure自動配置模塊有關(guān),所以spring-boot-starter-web模塊肯定是間接依賴了spring-boot-autoconfigure自動配置模塊。
spring-boot-starter模塊是絕大部分spring-boot-starter-xxx模塊依賴的基礎(chǔ)模塊,是核心的Starter,包括了自動配置,日志和YAML支持。我們此時來關(guān)注下spring-boot-starter的pom.xml文件,也許其依賴了了spring-boot-autoconfigure自動配置模塊。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
我們前面的猜想沒有錯,正是spring-boot-starter模塊依賴了spring-boot-autoconfigure自動配置模塊!因此,到了這里我們就可以得出結(jié)論了:spring-boot-starter-web模塊沒有一行代碼,但是其通過spring-boot-starter模塊間接依賴了spring-boot-autoconfigure自動配置模塊,從而實(shí)現(xiàn)了其起步依賴的功能。
我們再來看下spring-boot-autoconfigure自動配置模塊的內(nèi)部包結(jié)構(gòu):
我們可以知道spring-boot-starter-web起步依賴的自動配置功能原來是由spring-boot-autoconfigure模塊的web包下的類實(shí)現(xiàn)的。
到了這里spring-boot-starter-web起步依賴的構(gòu)建基本原理我們就搞清楚了,但是還有一個特別重要的關(guān)鍵點(diǎn)我們還沒Get到。這個關(guān)鍵點(diǎn)跟Maven的optional標(biāo)簽有的作用有關(guān)。
為了Get到這個點(diǎn),我們先來思考一個問題:平時我們開發(fā)web項(xiàng)目為什么引入了spring-boot-starter-web這個起步依賴后,spring-boot-autoconfigure模塊的web相關(guān)的自動配置類就會起自動起作用呢?
我們應(yīng)該知道,某個自動配置類起作用往往是由于classpath中存在某個類,這里以DispatcherServletAutoConfiguration這個自動配置類為切入點(diǎn)去Get這個點(diǎn)好了。
先看下DispatcherServletAutoConfiguration能夠自動配置的條件是啥?

由圖所示,DispatcherServletAutoConfiguration能夠自動配置的條件之一是@ConditionalOnClass(DispatcherServlet.class),即只有classpath中存在DispatcherServlet.class這個類,那么DispatcherServletAutoConfiguration自動配置相關(guān)邏輯才能起作用。
而DispatcherServlet這個類是在spring-webmvc這個依賴庫中的,如下圖所示:

此時我們再看下spring-boot-autoconfigure模塊的pom.xml文件引入spring-webmvc這個依賴的情況。spring-boot-autoconfigure模塊引入的spring-webmvc這個依賴時optional被設(shè)置為true,原來是可選依賴。即spring-webmvc這個依賴庫只會被導(dǎo)入到spring-boot-autoconfigure模塊中,而不會被導(dǎo)入到間接依賴spring-boot-autoconfigure模塊的spring-boot-starter-web這個起步依賴中。
spring-boot-starter-web起步依賴顯式引入了spring-webmvc這個依賴庫,即引入spring-webmvc 時沒有optional這個標(biāo)簽,又因?yàn)镈ispatcherServlet這個類是在spring-webmvc這個依賴庫中的,從而classpath中存在DispatcherServlet這個類,因此DispatcherServletAutoConfiguration這個自動配置類就生效了。當(dāng)然,web相關(guān)的其他自動配置類生效也是這個原理。
至此,我們也明白了spring-boot-autoconfigure模塊為什么要把引入的spring-webmvc這個依賴作為可選依賴了,其目的就是為了在spring-boot-starter-web起步依賴中能顯式引入spring-webmvc這個依賴(這個起決定性作用),從而我們開發(fā)web項(xiàng)目只要引入了spring-boot-starter-web起步依賴,那么web相關(guān)的自動配置類就生效,從而可以開箱即用這個就是spring-boot-starter-web這個起步依賴的構(gòu)建原理了。
總結(jié)
- spring-boot-starter-xxx起步依賴沒有一行代碼,而是直接或間接依賴了xxx-autoconfigure模塊,而xxx-autoconfigure模塊承擔(dān)了spring-boot-starter-xxx起步依賴自動配置的實(shí)現(xiàn);
- xxx-autoconfigure自動配置模塊引入了一些可選依賴,這些可選依賴不會被傳遞到spring-boot-starter-xxx起步依賴中,這是起步依賴構(gòu)建的關(guān)鍵點(diǎn);
- spring-boot-starter-xxx起步依賴顯式引入了一些對自動配置起作用的可選依賴;
經(jīng)過前面3步的準(zhǔn)備,我們項(xiàng)目只要引入了某個起步依賴后,就可以開箱即用了,而不用手動去創(chuàng)建一些bean等。