00 前言
在問了我自動配置的問題後,面試官又接着問了我知不知道springboot的starter是做什麼的?
我回答是就是集成依賴。面試官又問,怎麼自己實現一個starter?
我一下就懵了。
這個東西以前看過,但是沒有自己動手做過,只有一點點印象,所以直接回答了不知道。
事實上,在上一篇《我的面試(001)springboot是怎麼做到簡化配置的?》文章中將自動配置的問題搞清楚後,starter怎麼做的基本已經是呼之欲出了。
爲了加深記憶,我們就仿照源碼手碼一個starter出來吧。
01 新建starter
1、打開idea,File -> new -> Project,新建一個空項目。
2、點擊next,項目名起作yaomaomao-springboot-start。
3、Finish,選擇New Window,新打開一個idea項目工程。
4、新建一個module,我們開始創建starter模塊。
5、選擇maven,JDK我用的1.8。
6、填寫maven信息,GroupId我填的是com.yao.springboot-starter,AritfactId填的是yaomaomao-springboot-starter,version默認。
7、給module起個名字,module name 的名字我填的yaomaomao-springboot-starter,Content root及location同樣如此。
8、創建自動配置模塊,重複4、5、6的步驟,然後填寫maven信息,GroupId同樣填寫com.yao.springboot-starter,ArtifactId則不一樣,這裏我填寫的yaomaomao-springboot-stater-autoConfiguration。
9、與第7步一樣,配置moudle name :yaomaomao-springboot-stater-autoConfiguration。
02 怎麼進行自動裝配?
1、引用POM
打開yaomaomao-springboot-starter-autoconfigurer,在pom中引入spring-boot-starter,pom.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
6、starter中引用autoConfiguration
打開starter的module,在pom文件中添加如下內容,引入autoConfiguration
<dependencies>
<dependency>
<groupId>com.yao.springboot-starter</groupId>
<artifactId>yaomaomao-springboot-stater-autoConfiguration</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
至此,一個自定義starter就完成了。
接下來就是測試看看效果。
注意:如果想被其他項目使用,需要依次把configuration、starter這兩個module用maven 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 Services,next。
4、module name 設置爲yaomaomao-springboot-web
5、pom中引用starter
springboot 的web項目建立完畢,在pom中引用starter,添加內容如下:
<dependency>
<groupId>com.yao.springboot-starter</groupId>
<artifactId>yaomaomao-springboot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
6、application.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'
可以看到,是我們YaomaomaoService中connectJDBC方法展示的內容。
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源創計劃”,歡迎正在閱讀的你也加入,一起分享。