我的面試(002) springboot的starter是做什麼的?怎麼自己實現一個starter?


00 前言

在問了我自動配置的問題後,面試官又接着問了我知不知道springbootstarter是做什麼的?

我回答是就是集成依賴。面試官又問,怎麼自己實現一個starter

我一下就懵了。

這個東西以前看過,但是沒有自己動手做過,只有一點點印象,所以直接回答了不知道。

事實上,在上一篇《我的面試(001springboot是怎麼做到簡化配置的?》文章中將自動配置的問題搞清楚後,starter怎麼做的基本已經是呼之欲出了。

爲了加深記憶,我們就仿照源碼手碼一個starter出來吧。

01 新建starter

1、打開idea,File -> new -> Project,新建一個空項目。


 


2、點擊next,項目名起作yaomaomao-springboot-start


3Finish,選擇New Window,新打開一個idea項目工程。


4、新建一個module,我們開始創建starter模塊。

 

5、選擇mavenJDK我用的1.8

6、填寫maven信息,GroupId我填的是com.yao.springboot-starter,AritfactId填的是yaomaomao-springboot-starterversion默認。

7、給module起個名字,module name 的名字我填的yaomaomao-springboot-starterContent rootlocation同樣如此。

 

8、創建自動配置模塊,重複456的步驟,然後填寫maven信息,GroupId同樣填寫com.yao.springboot-starterArtifactId則不一樣,這裏我填寫的yaomaomao-springboot-stater-autoConfiguration

 

9、與第7步一樣,配置moudle name yaomaomao-springboot-stater-autoConfiguration

02 怎麼進行自動裝配?

1、引用POM

打開yaomaomao-springboot-starter-autoconfigurer,在pom中引入spring-boot-starterpom.xml如下:

<?xmlversion="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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.yao.springboot-starter</groupId>
 <artifactId>yaomaomao-springboot-stater-autoConfiguration</artifactId>
  <version>1.0-SNAPSHOT</version>

  <!--
指定springboot 依賴版本號-->
  <parent>
      <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.2.1.RELEASE</version>
      <relativePath/> <!-- lookup parent fromrepository -->
  </parent>

  <dependencies>
      <!--
引入spring-boot-starter;所有starter的基本配置-->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
  </dependencies>


</project>

2、創建YaomaomaoProperties

yaomaomao-springboot-starter-autoconfigurer這個module下,新建一個YaomaomaoProperties類,路徑爲src\main\java\com\yao

package com.yao;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Repository;

/**
* @author
姚毛毛
* @version V1.0
* @Description:
仿照dataSource寫個自動配置類
* @date 2020/02/29
*/
@ConfigurationProperties(prefix = "spring.yaomaomao")
//
此註解表示在application.properties中,以spring.yaomaomao爲前綴,映射賦值給這個類的字段
@Repository
public class YaomaomaoProperties {

  /*
連接地址 */
  private String url;

  /*
用戶 */
  private String userName;

  /*
密碼 */
  private String pwd;

  /*
數據庫類型 */
  private String type;

  /*
驅動包 */
  private String driverClassName;

  public String getUrl() {
      return url;
  }

  public void setUrl(String url) {
      this.url = url;
  }

  public String getUserName() {
      return userName;
  }

  public void setUserName(String userName) {
      this.userName = userName;
  }

  public String getPwd() {
      return pwd;
  }

  public void setPwd(String pwd) {
      this.pwd = pwd;
  }

  public String getType() {
      return type;
  }

  public void setType(String type) {
      this.type = type;
  }

  public String getDriverClassName() {
      return driverClassName;
  }

  public void setDriverClassName(String driverClassName) {
      this.driverClassName = driverClassName;
  }
}

3、創建YaomaomaoService

package com.yao;

public class YaomaomaoService {

  private YaomaomaoProperties yaomaomaoProperties;

  public void setYaomaomaoProperties(YaomaomaoPropertiesyaomaomaoProperties) {
      this.yaomaomaoProperties = yaomaomaoProperties;
  }

  public boolean connectJDBC() {

      System.out.println("
數據庫連接中");

      //
這裏只是僞代碼
      //
如果有數據庫,也可以真正地加載driverClassName,進行JDBC連接
      System.out.println( "url=" +yaomaomaoProperties.getUrl() +
              ",\n userName=" +yaomaomaoProperties.getUserName() +
              ",\n pwd=" +yaomaomaoProperties.getPwd() +
              ",\n type=" +yaomaomaoProperties.getType() +
              ",\ndriverClassName=" + yaomaomaoProperties.getDriverClassName() );

      System.out.println("
連接成功");
      return true;
  }

4、創建自動配置類YaomaomaoAutoConfiguration

package com.yao;

import org.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
importorg.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@EnableConfigurationProperties(YaomaomaoProperties.class) //
指定自動裝載類
@Configuration //
聲明是配置類
@ConditionalOnWebApplication // web
應用
public class YaomaomaoAutoConfiguration {

  @Autowired
  YaomaomaoProperties yaomaomaoProperties;

  @Bean
  public YaomaomaoService yaomaomaoService() {
      YaomaomaoService yaomaomaoService = newYaomaomaoService();
     yaomaomaoService.setYaomaomaoProperties(yaomaomaoProperties);
      return yaomaomaoService;
  }
}

5、創建spring.factories

resources下新建META-INF文件夾,創建spring.factories文件,指向我們的自動裝置類。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yao.YaomaomaoAutoConfiguration

6starter中引用autoConfiguration

打開startermodule,在pom文件中添加如下內容,引入autoConfiguration

<dependencies>
  <dependency>
      <groupId>com.yao.springboot-starter</groupId>
     <artifactId>yaomaomao-springboot-stater-autoConfiguration</artifactId>
      <version>1.0-SNAPSHOT</version>
  </dependency>
</dependencies>

至此,一個自定義starter就完成了。

接下來就是測試看看效果。

注意:如果想被其他項目使用,需要依次把configurationstarter這兩個modulemaven install 打包進本地倉庫,如圖:

 

03 測試使用starter

1、新建web 項目

新建一個springboot項目或者新建一個module都可以。如果是新建一個springboot項目,則需要將starter install進本地maven倉庫中,這裏爲了方便演示,是新建一個module

 

2、填寫相關信息:

group -> com.yao

Artifact -> yaosweb

name -> yaosweb

Package -> com.yao.yaosweb

 

3、選擇Web -> Spring Web Servicesnext


 


4module name 設置爲yaomaomao-springboot-web


 

5pom中引用starter

springboot web項目建立完畢,在pom中引用starter,添加內容如下:

<dependency>
  <groupId>com.yao.springboot-starter</groupId>
  <artifactId>yaomaomao-springboot-starter</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

6application.properties中配置內容

spring.yaomaomao.url=jdbc:oracle:thin:@192.168.1.8:1521:orcl
spring.yaomaomao.username=yaomaomao
spring.yaomaomao.password=pWd123969
spring.yaomaomao.type=com.alibaba.druid.pool.DruidDataSource
spring.yaomaomao.driverClassName=oracle.jdbc.driver.OracleDriver

7、編碼test

test中注入YaomaomaoService類,在contextLoads中調用connectJDBC()方法,內容如下:

packagecom.yao.yaosweb;

import com.yao.YaomaomaoService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class YaoswebApplicationTests {

  @Autowired
  YaomaomaoService yaomaomaoService;

  @Test
  void contextLoads() {
      yaomaomaoService.connectJDBC();
  }

}

8、執行結果

數據庫連接中
url=jdbc:oracle:thin:@192.168.1.8:1521:orcl,
userName=yaomaomao,
pwd=null,
type=com.alibaba.druid.pool.DruidDataSource,
driverClassName=oracle.jdbc.driver.OracleDriver
連接成功
2020-03-01 17:00:17.329 INFO 9820 --- [extShutdownHook]o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService'applicationTaskExecutor'

可以看到,是我們YaomaomaoServiceconnectJDBC方法展示的內容。

04 總結

最後,我們發現,其實starter是一個空jar。它唯一的目的是提供這個庫所必須的依賴。

一個完整的starter一般包含一個autoconfigure模塊(自動配置),一個starter模塊(提供對autoconfigure模塊及其它的依賴)。

再回憶下自定義starter的創建過程:

1、創建一個autoConfiguration模塊,pom引入org.spring.boot。

2、在autoConfiguration模塊下創建properties配置類,使用@ConfigurationProperties聲明,使用prefix指定前綴,定義儘可能使用到的字段屬性。

3、創建properties對應的service類,操作properties中的屬性進行業務操作。

4、創建autoConfiguration類,使用@EnableAutoConfiguration註解進行自動裝配,將service類注入到spring容器中。

5、創建META-INF/spring.factories,指定 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的value是 我們開啓自動裝配註解(@EnableAutoConfiguration)的類。

6、創建一個starter模塊,pom引入剛剛創建的autoConfiguration。

7、maven install 上面兩個module。

8、新建一個module或project,引用starter的maven包。

9、寫一個測試類,在application.properties文件中指定prefix前綴的配置變量,調用service中預先寫好的方法,看看是否起作用。

一句話總結下自定義starter的核心點,就是利用@EnableAutoConfiguration這個註解進行自動映射。

本次練習的代碼已在我的github上傳,地址爲:https://github.com/kiok1210/springboot-learn。



 


本文分享自微信公衆號 - 架構師之殤(ysistrue)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章