Spring Boot Starter 是在 SpringBoot 組件中被提出來的一種概念,stackoverflow 上面已經有人歸納了這個 starter 是什麼東西,想看完整的回答戳 這裏。html
Starter POMs are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.git
大概意思就是說 starter 是一種對依賴的 synthesize(合成),這是什麼意思呢?我能夠舉個例子來講明。github
在沒有 starter 以前,假如我想要在 Spring 中使用 jpa,那我可能須要作如下操做:web
須要注意的是,這裏操做在咱們 每次新建一個須要用到 jpa 的項目的時候都須要重複的作一次。也許你在第一次本身創建項目的時候是在 Google 上本身搜索了一番,花了半天時間解決掉了各類奇怪的問題以後,jpa 終於能正常運行了。有些有經驗的人會在 OneNote 上面把此次創建項目的過程給記錄下來,包括操做的步驟以及須要用到的配置文件的內容,在下一次再建立 jpa 項目的時候,就不須要再次去 Google 了,只須要照着筆記來,以後再把全部的配置文件 copy&paste 就能夠了。spring
像上面這樣的操做也不算不行,事實上咱們在沒有 starter 以前都是這麼幹的,可是這樣作有幾個問題:數據庫
starter 的主要目的就是爲了解決上面的這些問題。apache
starter 的理念:starter 會把全部用到的依賴都給包含進來,避免了開發者本身去引入依賴所帶來的麻煩。須要注意的是不一樣的 starter 是爲了解決不一樣的依賴,因此它們內部的實現可能會有很大的差別,例如 jpa 的 starter 和 Redis 的 starter 可能實現就不同,這是由於 starter 的本質在於 synthesize,這是一層在邏輯層面的抽象,也許這種理念有點相似於 Docker,由於它們都是在作一個 「包裝」 的操做,若是你知道 Docker 是爲了解決什麼問題的,也許你能夠用 Docker 和 starter 作一個類比。app
starter 的實現:雖然不一樣的 starter 實現起來各有差別,可是他們基本上都會使用到兩個相同的內容:ConfigurationProperties 和 AutoConfiguration。由於 Spring Boot 堅信 「約定大於配置」 這一理念,因此咱們使用 ConfigurationProperties 來保存咱們的配置,而且這些配置均可以有一個默認值,即在咱們沒有主動覆寫原始配置的狀況下,默認值就會生效,這在不少狀況下是很是有用的。除此以外,starter 的 ConfigurationProperties 還使得全部的配置屬性被彙集到一個文件中(通常在 resources 目錄下的 application.properties),這樣咱們就告別了 Spring 項目中 XML 地獄。maven
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
文件以下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>http-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 自定義starter都應該繼承自該依賴 -->
<!-- 若是自定義starter自己須要繼承其它的依賴,能夠參考 https://stackoverflow.com/a/21318359 解決 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<!-- 自定義starter依賴此jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- lombok用於自動生成get、set方法 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
</project>
建立 proterties 類來保存配置信息:
@ConfigurationProperties(prefix = "http") // 自動獲取配置文件中前綴爲http的屬性,把值傳入對象參數
@Setter
@Getter
public class HttpProperties {
// 若是配置文件中配置了http.url屬性,則該默認屬性會被覆蓋
private String url = "http://www.baidu.com/";
}
上面這個類就是定義了一個屬性,其默認值是 http://www.baidu.com/
,咱們能夠經過在 application.properties
中添加配置 http.url=https://www.zhihu.com
來覆蓋參數的值。
建立業務類:
@Setter
@Getter
public class HttpClient {
private String url;
// 根據url獲取網頁數據
public String getHtml() {
try {
URL url = new URL(this.url);
URLConnection urlConnection = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
}
這個業務類的操做很是簡單,只包含了一個 url
屬性和一個 getHtml
方法,用於獲取一個網頁的 HTML 數據,讀者看看就懂了。
建立 AutoConfiguration
@Configuration
@EnableConfigurationProperties(HttpProperties.class)
public class HttpAutoConfiguration {
@Resource
private HttpProperties properties; // 使用配置
// 在Spring上下文中建立一個對象
@Bean
@ConditionalOnMissingBean
public HttpClient init() {
HttpClient client = new HttpClient();
String url = properties.getUrl();
client.setUrl(url);
return client;
}
}
在上面的 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,代碼以下:
@Component
public class RunIt {
@Resource
private HttpClient httpClient;
public void hello() {
System.out.println(httpClient.getHtml());
}
}
正常狀況下此方法的執行會打印出 url http://www.baidu.com/
的 HTML 內容,以後咱們在 application.properties 中加入配置:
http.url=https://www.zhihu.com/
再次運行程序,此時打印的結果應該是知乎首頁的 HTML 了,證實 properties 中的數據確實被覆蓋了。
本文轉載自:御阪研究所
原文連接:https://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/