Spring Boot Starters是什麼?

版權聲明:該文轉自: 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,那我可能須要作如下操做:數據庫

  1. 在Maven中引入使用的數據庫的依賴(即JDBC的jar)
  2. 引入jpa的依賴
  3. 在xxx.xml中配置一些屬性信息
  4. 反覆的調試直到能夠正常運行

  須要注意的是,這裏操做在咱們每次新建一個須要用到jpa的項目的時候都須要重複的作一次。也許你在第一次本身創建項目的時候是在Google上本身搜索了一番,花了半天時間解決掉了各類奇怪的問題以後,jpa終於能正常運行了。有些有經驗的人會在OneNote上面把此次創建項目的過程給記錄下來,包括操做的步驟以及須要用到的配置文件的內容,在下一次再建立jpa項目的時候,就不須要再次去Google了,只須要照着筆記來,以後再把全部的配置文件copy&paste就能夠了。apache

  像上面這樣的操做也不算不行,事實上咱們在沒有starter以前都是這麼幹的,可是這樣作有幾個問題:app

  1. 若是過程比較繁瑣,這樣一步步操做會增長出錯的可能性
  2. 不停地copy&paste不符合Don’t repeat yourself精神
  3. 在第一次配置的時候(尤爲若是開發者比較小白),須要花費掉大量的時間

  使用Spring Boot Starter提高效率

  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的列表。

  建立本身的Spring Boot Starter

  若是你想要本身建立一個starter,那麼基本上包含如下幾步

  1. 建立一個starter項目,關於項目的命名你能夠參考這裏
  2. 建立一個ConfigurationProperties用於保存你的配置信息(若是你的項目不使用配置信息則能夠跳過這一步,不過這種狀況很是少見)
  3. 建立一個AutoConfiguration,引用定義好的配置信息;在AutoConfiguration中實現全部starter應該完成的操做,而且把這個類加入spring.factories配置文件中進行聲明
  4. 打包項目,以後在一個SpringBoot項目中引入該項目依賴,而後就可使用該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中的數據確實被覆蓋了。

相關文章
相關標籤/搜索