版權聲明:該文轉自: http://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/。版權歸原創做者,在此對原做者的付出表示感謝!html
starter是SpringBoot中的一個新發明,它有效的下降了項目開發過程的複雜程度,對於簡化開發操做有着很是好的效果。本文轉載了一片文章,詳細介紹了spring boot stater是什麼?它的做用是什麼?git
Spring Boot Starter是在SpringBoot組件中被提出來的一種概念,stackoverflow上面已經有人歸納了這個starter是什麼東西,想看完整的回答戳這裏(https://stackoverflow.com/questions/28273543/what-are-spring-boot-starter-jars/28273660#28273660)github
大概意思就是說starter是一種對依賴的synthesize(合成),這是什麼意思呢?我能夠舉個例子來講明。spring
在沒有starter以前,假如我想要在Spring中使用jpa,那我可能須要作如下操做:數據庫
須要注意的是,這裏操做在咱們每次新建一個須要用到jpa的項目的時候都須要重複的作一次。也許你在第一次本身創建項目的時候是在Google上本身搜索了一番,花了半天時間解決掉了各類奇怪的問題以後,jpa終於能正常運行了。有些有經驗的人會在OneNote上面把此次創建項目的過程給記錄下來,包括操做的步驟以及須要用到的配置文件的內容,在下一次再建立jpa項目的時候,就不須要再次去Google了,只須要照着筆記來,以後再把全部的配置文件copy&paste就能夠了。apache
像上面這樣的操做也不算不行,事實上咱們在沒有starter以前都是這麼幹的,可是這樣作有幾個問題:app
starter的主要目的就是爲了解決上面的這些問題。maven
starter的理念:starter會把全部用到的依賴都給包含進來,避免了開發者本身去引入依賴所帶來的麻煩。須要注意的是不一樣的starter是爲了解決不一樣的依賴,因此它們內部的實現可能會有很大的差別,例如jpa的starter和Redis的starter可能實現就不同,這是由於starter的本質在於synthesize,這是一層在邏輯層面的抽象,也許這種理念有點相似於Docker,由於它們都是在作一個「包裝」的操做,若是你知道Docker是爲了解決什麼問題的,也許你能夠用Docker和starter作一個類比。spring-boot
starter的實現:雖然不一樣的starter實現起來各有差別,可是他們基本上都會使用到兩個相同的內容:ConfigurationProperties和AutoConfiguration。由於Spring Boot堅信「約定大於配置」這一理念,因此咱們使用ConfigurationProperties來保存咱們的配置,而且這些配置均可以有一個默認值,即在咱們沒有主動覆寫原始配置的狀況下,默認值就會生效,這在不少狀況下是很是有用的。除此以外,starter的ConfigurationProperties還使得全部的配置屬性被彙集到一個文件中(通常在resources目錄下的application.properties),這樣咱們就告別了Spring項目中XML地獄。ui
starter的總體邏輯:
上面的starter依賴的jar和咱們本身手動配置的時候依賴的jar並無什麼不一樣,因此咱們能夠認爲starter實際上是把這一些繁瑣的配置操做交給了本身,而把簡單交給了用戶。除了幫助用戶去除了繁瑣的構建操做,在「約定大於配置」的理念下,ConfigurationProperties還幫助用戶減小了無謂的配置操做。而且由於 application.properties
文件的存在,即便須要自定義配置,全部的配置也只須要在一個文件中進行,使用起來很是方便。
瞭解了starter其實就是幫助用戶簡化了配置的操做以後,要理解starter和被配置了starter的組件之間並非競爭關係,而是輔助關係,即咱們能夠給一個組件建立一個starter來讓最終用戶在使用這個組件的時候更加的簡單方便。基於這種理念,咱們能夠給任意一個現有的組件建立一個starter來讓別人在使用這個組件的時候更加的簡單方便,事實上Spring Boot團隊已經幫助現有大部分的流行的組件建立好了它們的starter,你能夠在這裏查看這些starter的列表。
若是你想要本身建立一個starter,那麼基本上包含如下幾步
咱們來看一個例子(例子的完整代碼位於https://github.com/RitterHou/learn-spring-boot-starter)
首先新建一個Maven項目,設置 pom.xml
文件以下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 <artifactId>http-starter</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 9 <!-- 自定義starter都應該繼承自該依賴 --> 10 <!-- 若是自定義starter自己須要繼承其它的依賴,能夠參考 https://stackoverflow.com/a/21318359 解決 --> 11 <parent> 12 <groupId>org.springframework.boot</groupId> 13 <artifactId>spring-boot-starters</artifactId> 14 <version>1.5.2.RELEASE</version> 15 </parent> 16 17 <dependencies> 18 <!-- 自定義starter依賴此jar包 --> 19 <dependency> 20 <groupId>org.springframework.boot</groupId> 21 <artifactId>spring-boot-starter</artifactId> 22 </dependency> 23 <!-- lombok用於自動生成get、set方法 --> 24 <dependency> 25 <groupId>org.projectlombok</groupId> 26 <artifactId>lombok</artifactId> 27 <version>1.16.10</version> 28 </dependency> 29 </dependencies> 30 31 </project>
建立proterties類來保存配置信息:
1 @ConfigurationProperties(prefix = "http") // 自動獲取配置文件中前綴爲http的屬性,把值傳入對象參數 2 @Setter 3 @Getter 4 public class HttpProperties { 5 6 // 若是配置文件中配置了http.url屬性,則該默認屬性會被覆蓋 7 private String url = "http://www.baidu.com/"; 8 9 }
上面這個類就是定義了一個屬性,其默認值是 http://www.baidu.com/
,咱們能夠經過在 application.properties
中添加配置 http.url=https://www.zhihu.com
來覆蓋參數的值。
建立業務類:
1 @Setter 2 @Getter 3 public class HttpClient { 4 5 private String url; 6 7 // 根據url獲取網頁數據 8 public String getHtml() { 9 try { 10 URL url = new URL(this.url); 11 URLConnection urlConnection = url.openConnection(); 12 BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8")); 13 String line = null; 14 StringBuilder sb = new StringBuilder(); 15 while ((line = br.readLine()) != null) { 16 sb.append(line).append("\n"); 17 } 18 return sb.toString(); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 return "error"; 23 } 24 25 }
這個業務類的操做很是簡單,只包含了一個 url
屬性和一個 getHtml
方法,用於獲取一個網頁的HTML數據,讀者看看就懂了。
建立AutoConfiguration
1 @Configuration 2 @EnableConfigurationProperties(HttpProperties.class) 3 public class HttpAutoConfiguration { 4 5 @Resource 6 private HttpProperties properties; // 使用配置 7 8 // 在Spring上下文中建立一個對象 9 @Bean 10 @ConditionalOnMissingBean 11 public HttpClient init() { 12 HttpClient client = new HttpClient(); 13 14 String url = properties.getUrl(); 15 client.setUrl(url); 16 return client; 17 } 18 19 }
在上面的AutoConfiguration中咱們實現了本身要求:在Spring的上下文中建立了一個HttpClient類的bean,而且咱們把properties中的一個參數賦給了該bean。
關於@ConditionalOnMissingBean
這個註解,它的意思是在該bean不存在的狀況下此方法纔會執行,這個至關於開關的角色,更多關於開關係列的註解能夠參考這裏。
最後,咱們在 resources
文件夾下新建目錄 META-INF
,在目錄中新建 spring.factories
文件,而且在 spring.factories
中配置AutoConfiguration:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.nosuchfield.httpstarter.HttpAutoConfiguration
到此,咱們的starter已經建立完畢了,使用Maven打包該項目。以後建立一個SpringBoot項目,在項目中添加咱們以前打包的starter做爲依賴,而後使用SringBoot來運行咱們的starter,代碼以下:
1 @Component 2 public class RunIt { 3 4 @Resource 5 private HttpClient httpClient; 6 7 public void hello() { 8 System.out.println(httpClient.getHtml()); 9 } 10 11 }
正常狀況下此方法的執行會打印出url http://www.baidu.com/
的HTML內容,以後咱們在application.properties中加入配置:
http.url=https://www.zhihu.com/
再次運行程序,此時打印的結果應該是知乎首頁的HTML了,證實properties中的數據確實被覆蓋了。