天天看點

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

之前熟悉了SpringBoot的自動配置原理,相關連結:SpringBoot學習之自動配置原理,今天來玩一下自定義起步依賴starter。

一、分析

以jdbc下DataSource自動配置參考為例:

1.DataSourceAutoConfiguration

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
...
           

2.DataSourceProperties

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
		implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {

	private ClassLoader classLoader;

	private Environment environment;
	...
           

3.spring.factories配置

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

4.總結

(1)自動配置的大體流程

1)@Configuration //指定一個配置類

2)@Conditionalxxx //在指定條件成立時自動配置類生效

3)@EnableConfigurationProperties //讓xxxProperties檔案生效并加入到容器

4)@ConfigurationProperties //注解相關xxxProperties檔案來綁定相關屬性

5)在META-INF 下的spring.factories中配置該自動配置類

(2)開始自定義starter

接下來分兩步走:

  • 第一是自定義starter并調試,在一個工程中驗證;
  • 第二是參照其他起步依賴配置模式打包生成自己的起步依賴starter

二、編寫starter并調試

以自定義HttpClient自動配置為例:

1、建立一個Springboot工程

2、導入httpclient依賴

<!--導入httpclient依賴-->
 	<dependency>
 		<groupId>org.apache.httpcomponents</groupId>
 		<artifactId>httpclient</artifactId>
 	</dependency>

           

3、建立HttpClientProperties

/**
* @description: httpclient 屬性配置類
*  在application.properties中進行配置,可以覆寫各屬性的預設值
* @author: zrk
* @create: 2019-03-08
*/
@ConfigurationProperties(prefix = "zrk.httpclient")
public class HttpClientProperties {
 private Integer connectTimeOut = 1000;

 private Integer socketTimeOut = 10000;

 private String agent = "agent";

 private Integer maxConnPreRoute = 10;

 private Integer maxConnTotal = 50;

 public Integer getConnectTimeOut() {
     return connectTimeOut;
 }

 public void setConnectTimeOut(Integer connectTimeOut) {
     this.connectTimeOut = connectTimeOut;
 }

 public Integer getSocketTimeOut() {
     return socketTimeOut;
 }

 public void setSocketTimeOut(Integer socketTimeOut) {
     this.socketTimeOut = socketTimeOut;
 }

 public String getAgent() {
     return agent;
 }

 public void setAgent(String agent) {
     this.agent = agent;
 }

 public Integer getMaxConnPreRoute() {
     return maxConnPreRoute;
 }

 public void setMaxConnPreRoute(Integer maxConnPreRoute) {
     this.maxConnPreRoute = maxConnPreRoute;
 }

 public Integer getMaxConnTotal() {
     return maxConnTotal;
 }

 public void setMaxConnTotal(Integer maxConnTotal) {
     this.maxConnTotal = maxConnTotal;
 }
}
           

4、建立HttpClientAutoConfiguration

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
/**
 * @description: httpclient自動配置類
 * @author: zrk
 * @create: 2019-03-08
 */
@Configuration //配置類
@ConditionalOnClass({HttpClient.class}) //生效條件是HttpClient存在
@EnableConfigurationProperties(HttpClientProperties.class) //讓配置檔案生效并加入到容器
public class HttpClientAutoConfiguration {

    private final HttpClientProperties httpClientProperties;

    public HttpClientAutoConfiguration(HttpClientProperties httpClientProperties) {
        this.httpClientProperties = httpClientProperties;
    }

    @Bean
    @ConditionalOnMissingBean(HttpClient.class) //當容器中不存在HttpClient實力時此bean才加入容器
    public HttpClient httpClient(){
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(httpClientProperties.getConnectTimeOut())
                .setSocketTimeout(httpClientProperties.getSocketTimeOut())
                .build();
        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setMaxConnPerRoute(httpClientProperties.getMaxConnPreRoute())
                .setMaxConnTotal(httpClientProperties.getMaxConnTotal())
                .setUserAgent(httpClientProperties.getAgent())
                .build();
    }
}
           

5、編寫測試類并運作

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
@RunWith(SpringRunner.class)
@SpringBootTest
public class HttpclientApplicationTests {

	@Resource
	HttpClient httpClient;

	@Test
	public void httpclientTest() throws IOException {
		System.out.println(EntityUtils.toString(httpClient.execute(new HttpGet("http://www.baidu.com")).getEntity()));
	}
}
           

運作測試方法,控制台如下:

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

如圖,可以正常通路并列印,證明自動配置已經生效。

但是現在暫未在META-INF中進行配置,自動配置生效是因為根據SpringBoot包掃描原理會掃描主啟動類所在目錄及以下目錄的包(可以參考SpringBoot學習之包掃描),配置類在此子包中是以可以掃描到容器。

但作為起步依賴包讓其他項目用是不再包掃描範圍内的,接下來就用兩種方式示範在掃描包之外路徑如何使自動配置生效:

(1)在META-INF/spring.properties中配置

修改包名

移動包使其不在自動包掃描範圍内

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

運作測試方法,報錯,就是因為沒有在容器中找到HttpClient的bean執行個體

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

建立META-INF/spring.properties檔案并配置

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zrk.httpclient1.autoconfigure.HttpClientAutoConfiguration
           

運作測試方法,成功:

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

(2)自定義注解

參考@EnableAsync方式:

先将META-INF/spring.properties删除或改名使其不生效,再建立EnableHttpClient annotation

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

在主啟動類上添加@EnableHttpClient注解

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

運作測試方法,成功:

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

三、正式編寫starter并打包

參考MyBatis起步依賴模式:

  • 啟動器做依賴導入
  • 編寫自動配置子產品
  • 啟動器依賴自動配置

    這樣需要依賴MyBatis時隻需導入啟動器starter即可,也可以直接寫自動配置子產品

    自定義starter命名參考:

    mybatis-spring-boot-starter -> 功能-spring-boot-starter

1、建立個空工程

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

2、添加兩個modules

(1)啟動器

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

(2)自動配置子產品

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

直至建立完成,點OK

3、在啟動器pom檔案中引入自動配置子產品的坐标依賴

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

4、編寫自動配置子產品代碼

添加自動配置類、添加屬性配置類、添加META-INF/spring.factories檔案,可以參考上面,這裡不再贅述

因為是作為第三方依賴,是以測試依賴跟相關插件等依賴可以删除

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

5、打包

先打包自動配置子產品,再打包啟動器

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

6、建立新工程導入自定義starter進行測試

導入自定義starter:

<!--導入自定義starter-->
		<dependency>
			<groupId>com.zrk.autoconfigure</groupId>
			<artifactId>httpclient-spring-boot-starter</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
           

建立controller:

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結
@RestController
public class HttpClientController {

    @Resource
    private HttpClient httpClient;

    @RequestMapping("goto")
    public String request(){
        try {
            return EntityUtils.toString(httpClient.execute(new HttpGet("http://www.baidu.com")).getEntity());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
}
           

啟動項目,通路http://localhost:8080/goto,雖有中文亂碼,但是自動配置是生效了~

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

打斷點,調試如下

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

修改application.properties

zrk.httpclient.connectTimeOut=2000
zrk.httpclient.socketTimeOut=20000
           

重新開機項目,通路調試如下

SpringBoot學習之自定義starter一、分析二、編寫starter并調試三、正式編寫starter并打包四、總結

四、總結

總之,參考源代碼,了解架構的設計思路,并按照總結的方式一步步跟着玩,就可以學會自定義starter。

繼續閱讀