面试重点:starter原理以及自己动手实现一个starter
目錄
- 前言
- starter的有關規范
- 結構
- 命名
- 自定義starter
- 新建項目
- 新建starter模塊
- 新建autoconfigure模塊
- 配置autoconfigure模塊
- pom依賴
- xxxProperties配置
- 服務提供類
- 自動配置
- META-INF/spring.factories
- 打包構建
- 測試
- 總結
前言
使用過Spring Boot的同學,都應該對starter不陌生,starter可以看過是一個個組件,用于提供不同的功能。Spring官方提供了很多starter,對應于不同的應用場景,以下為部分實現:
在我們需要某種功能的時候,只需要簡單地導入一個starter就可以直接使用。那么為什么只要導入starter就能使用這些功能呢,Spring Boot是如何做到的?下邊就通過自己實現一個starter來捋一捋這其中的流程。
在這篇文章 源碼分析——Spring Boot是如何實現自動配置的 中
,我簡單分析了下Spring Boot自動配置的相關原理。簡單總結就是:
其實starter的實現也是基于Spring Boot的自動配置來實現的,下邊就參考官方文檔(Creating Your Own Starter)來自己動手實現一個starter。
starter的有關規范
結構
一步步參考官方文檔來:
首先可以看到,規范的starter包含兩個model,一個autoconfigure,提供自動配置代碼,一個starter,會加載 autoconfigure,并提供啟動所需的所有依賴。
這里我的理解是 莫非還是為了解耦?starter只管啟動,具體的配置啥的都交給autoconfigure,這里就看自己的理解了。
命名
接下來是命名,這里就不截取官方文檔的原文了,大概意思就是:
這里是一些基本的規范,其它的規范到具體應用再說。
自定義starter
新建項目
接下來按照規范,一步步來創建自己的starter。首先創建一個空的Project。用以承載starter和autoconfigure兩個model。
這里命名不重要,只要具體的模塊按照規范命名即可。
新建starter模塊
接下來在當前Project下新建model,這里我選擇先創建starter:
創建maven工程
這里GroupId和ArtifactId相當于是Maven項目的三維坐標(一般還有個版本號)。當你把自己的項目發布到maven倉庫后,他人若想使用你的項目,就通過這兩個坐標來引入。其中GroupId類似代表企業,一般是域名反寫,ArtifactId一般是具體的項目名,對于starter而言,規范就是xxx-spring-boot-starter,比如mybatis和druid的starter:
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.2</version> </dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.22</version> </dependency>這里我新建一個myservice的starter,做如下命名:
新建autoconfigure模塊
建好后,我們再去新建autoconfigure這個model,這里因為是要借助Spring Boot做自動配置,就可以直接使用Spring Initializer來創建。
這里依然按照規范,ArtifactId為myservice-spring-boot-autoconfigure
然后什么都不導入,直接一路next,finish。
配置autoconfigure模塊
pom依賴
修改pom文件,刪除無關依賴:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>cn.novalue.starter</groupId><artifactId>myservice-spring-boot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version><name>myservice-spring-boot-autoconfigure</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies></project>這里 spring-boot-starter的依賴是一定要有的,官方文檔說了,starter模塊要直接或者間接導入該模塊,這里就把它放到autoconfigure模塊下了。當然這里的依賴放置可能并不是很規范,只是為了學習罷了。
Either way, your starter must reference the core Spring Boot starter (spring-boot-starter) directly or indirectly (i.e. no need to add it if your starter relies on another starter). If a project is created with only your custom starter, Spring Boot’s core features will be honoured by the presence of the core starter.
由于我們這個模塊只管配置,那么把啟動類也刪除了,test文件夾也刪除,配置文件application.properties也可以刪除了。
xxxProperties配置
按照開頭的自動配置描述,新建一個MyProperties配置類。
@ConfigurationProperties(prefix = "myservice") public class MyProperties {private String prefix;private String suffix;public String getPrefix() {return prefix;}public String getSuffix() {return suffix;}public void setPrefix(String prefix) {this.prefix = prefix;}public void setSuffix(String suffix) {this.suffix = suffix;} }這里注解 @ConfigurationProperties 表示這是一個配置文件,其中的屬性字段可以在application.properties中指定。prefix = "myservice"表示匹配 myservice前綴。例如這里,我們將來使用的時候就可以通過配置myservice.prefix=xxx來配置前綴。
服務提供類
然后我們新建個MyService服務類,表示我們這個starter可以提供的服務。
public class MyService {private MyProperties myProperties;public MyService(MyProperties myProperties) {this.myProperties = myProperties;}public String addPrefix(String s) {return this.myProperties.getPrefix() + "-" + s;} }這里把配置文件作為構造方法參數傳遞進去,然后在具體服務中使用,這里只簡單的提供一個添加前綴的服務。
自動配置
最后一步,就是編寫一個自動配置類,綁定我們的配置文件、并將我們的服務注入到spring容器。如下:
// 必須,指明這是一個配置類 @Configuration // 可選,表示在web應用中才配置 @ConditionalOnWebApplication // 必須,綁定我們的配置文件類 @EnableConfigurationProperties(MyProperties.class) // 可選,表示可以在配置文件中,通過myservice.enable來設置是否配置該類 // 如果沒有指明,則默認為true,即表示配置,如果指明為false,就不配置了 @ConditionalOnProperty(prefix = "myservice", value = "enable", matchIfMissing = true) public class MyServiceAutoConfiguration {// 注入配置文件@AutowiredMyProperties myProperties;// 用@Bean將MyService注入到Spring容器中,并把配置文件傳進去,以供MyService使用@Beanpublic MyService myService() {return new MyService(myProperties);} }這里關于自動配置有很多相關的注解,提供了更細粒度的配置控制,比如@Conditionalxxx系列,表示在滿足什么條件下才配置。或者@AutoConfigureOrder指定順序等等,可根據具體需求選擇配置。
META-INF/spring.factories
在前邊說過,Spring Boot的自動配置會自動加載類路徑下META-INF/spring.factories文件,并將以類EnableAutoConfiguration的全限定類名對應的值作為候選配置類。所以這里還需要新建該文件。
這樣,Spring Boot就能自動掃描到我們這個配置類并加載了。
打包構建
編寫完后,將兩個模塊打包發布到maven倉庫。因為導入的時候是從maven倉庫查找的。這里說一點,我們默認打包發布是發布在我們本地的maven倉庫的,所以只能本地使用。如果想要將自己的服務公開出去,可以查找發布到maven中心倉庫的方法。
IDEA可以很簡單地執行打包操作:
以此打包好autoconfigure模塊和starter模塊。
到此,自定義starter就算完成了,下邊測試一下。
測試
可以新建個Spring Boot的maven項目測試,這里我省事,就還在原Project下新建model測試了,效果一樣的。
因為我們寫的自動配置有個@ConditionalOnWebApplication,表示在Web應用程序下才配置,所以這里要勾選Spring Web。
新建完成后,在pom.xml中導入我們的starter依賴
<dependency><groupId>cn.novalue.starter</groupId><artifactId>myservice-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version></dependency>作為測試,可以在application.properties文件中,做自定義配置,比如設置前綴:
myservice.prefix=this is prefix新建一個TestController,注入我們的MyService:
@RestController public class TestController {@Autowiredprivate MyService myService;@GetMapping("/test")public String test() {return myService.addPrefix("test MyService");} }這里調用myService.addPrefix。啟動項目,瀏覽器輸入http://localhost:8080/test:
說明我們確實可以使用myService的服務,并且可以自定義前綴。
總結
總結自定義starter的主要流程和注意事項:
總結
以上是生活随笔為你收集整理的面试重点:starter原理以及自己动手实现一个starter的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [算法系列]优先队列,堆与堆排序
- 下一篇: dw实现html实时更新,DW在HTML