SpringBoot應用篇(一):自定義starter

超級小小黑發表於2019-05-15

一、碼前必備知識

1、SpringBoot starter機制

  SpringBoot中的starter是一種非常重要的機制,能夠拋棄以前繁雜的配置,將其統一整合進starter,應用者只需要在maven中引入starter依賴,SpringBoot就能自動掃描到要載入的資訊並啟動相應的預設配置。starter讓我們擺脫了各種依賴庫的處理,需要配置各種資訊的困擾。SpringBoot會自動通過classpath路徑下的類發現需要的Bean,並註冊進IOC容器。SpringBoot提供了針對日常企業應用研發各種場景的spring-boot-starter依賴模組。所有這些依賴模組都遵循著約定成俗的預設配置,並允許我們調整這些配置,即遵循“約定大於配置”的理念。

2、為什麼要自定義starter

  在我們的日常開發工作中,經常會有一些獨立於業務之外的配置模組,我們經常將其放到一個特定的包下,然後如果另一個工程需要複用這塊功能的時候,需要將程式碼硬拷貝到另一個工程,重新整合一遍,麻煩至極。如果我們將這些可獨立於業務程式碼之外的功配置模組封裝成一個個starter,複用的時候只需要將其在pom中引用依賴即可,SpringBoot為我們完成自動裝配,簡直不要太爽。

3、自定義starter的案例

  以下案例由筆者工作中遇到的部分場景

  ▲ 動態資料來源。

  ▲ 登入模組。

  ▲ 基於AOP技術實現日誌切面。

  。。。。。。

4、自定義starter的命名規則

  SpringBoot提供的starter以spring-boot-starter-xxx的方式命名的。官方建議自定義的starter使用xxx-spring-boot-starter命名規則。以區分SpringBoot生態提供的starter。

二、starter的實現方法

1、新建一個工程

  命名為demo-spring-boot-starter

  下圖為工程目錄結構

  

2、pom依賴

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5     <parent>
 6         <groupId>org.springframework.boot</groupId>
 7         <artifactId>spring-boot-starter-parent</artifactId>
 8         <version>2.1.4.RELEASE</version>
 9     </parent>
10     <groupId>com.demo</groupId>
11     <artifactId>demo-spring-boot-starter</artifactId>
12     <version>0.0.1-RELEASE</version>
13     <name>demo-spring-boot-starter</name>
14     <description>Demo project for Spring Boot</description>
15 
16     <properties>
17         <java.version>1.8</java.version>
18     </properties>
19 
20     <dependencies>
21 
22         <dependency>
23             <groupId>org.springframework.boot</groupId>
24             <artifactId>spring-boot-configuration-processor</artifactId>
25             <optional>true</optional>
26         </dependency>
27 
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter</artifactId>
31         </dependency>
32     </dependencies>
33 </project>

 

 

3、定義一個實體類對映配置資訊

 @ConfigurationProperties(prefix = "demo") 它可以把相同字首的配置資訊通過配置項名稱對映成實體類,比如我們這裡指定 prefix = "demo" 這樣,我們就能將以demo為字首的配置項拿到了。
ps:其實這個註解很強大,它不但能對映簡單的key-value的形式。還可以對映為List,Map等資料結構。
 1 package com.demo.starter.properties;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 
 5 /**
 6  * 描述:配置資訊 實體
 7  *
 8  * @Author shf
 9  * @Date 2019/5/7 22:08
10  * @Version V1.0
11  **/
12 @ConfigurationProperties(prefix = "demo")
13 public class DemoProperties {
14     private String sayWhat;
15     private String toWho;
16 
17     public String getSayWhat() {
18         return sayWhat;
19     }
20 
21     public void setSayWhat(String sayWhat) {
22         this.sayWhat = sayWhat;
23     }
24 
25     public String getToWho() {
26         return toWho;
27     }
28 
29     public void setToWho(String toWho) {
30         this.toWho = toWho;
31     }
32 }

 

 

4、定義一個Service

 1 package com.demo.starter.service;
 2 
 3 /**
 4  * 描述:隨便定義一個Service
 5  *
 6  * @Author shf
 7  * @Date 2019/5/7 21:59
 8  * @Version V1.0
 9  **/
10 public class DemoService {
11     public String sayWhat;
12     public String toWho;
13     public DemoService(String sayWhat, String toWho){
14         this.sayWhat = sayWhat;
15         this.toWho = toWho;
16     }
17     public String say(){
18         return this.sayWhat + "!  " + toWho;
19     }
20 }

 

 

5,定義一個配置類

這裡,我們將DemoService類定義為一個Bean,交給Ioc容器。

▲  @Configuration 註解就不多說了。

▲  @EnableConfigurationProperties 註解。該註解是用來開啟對3步驟中 @ConfigurationProperties 註解配置Bean的支援。也就是@EnableConfigurationProperties註解告訴Spring Boot 能支援@ConfigurationProperties。

當然了,也可以在 @ConfigurationProperties 註解的類上新增 @Configuration 或者  @Component 註解

▲  @ConditionalOnProperty 註解控制 @Configuration 是否生效。簡單來說也就是我們可以通過在yml配置檔案中控制 @Configuration 註解的配置類是否生效。

 

 1 package com.demo.starter.config;
 2 
 3 import com.demo.starter.properties.DemoProperties;
 4 import com.demo.starter.service.DemoService;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 7 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.context.annotation.Configuration;
10 
11 /**
12  * 描述:配置類
13  *
14  * @Author shf
15  * @Date 2019/5/7 21:50
16  * @Version V1.0
17  **/
18 @Configuration
19 @EnableConfigurationProperties(DemoProperties.class)
20 @ConditionalOnProperty(
21         prefix = "demo",
22         name = "isopen",
23         havingValue = "true"
24 )
25 public class DemoConfig {
26     @Autowired
27     private DemoProperties demoProperties;
28 
29     @Bean(name = "demo")
30     public DemoService demoService(){
31         return new DemoService(demoProperties.getSayWhat(), demoProperties.getToWho());
32     }
33 }

 

 6、最重要的來了

如圖,新建META-INF資料夾,然後建立spring.factories檔案,

 在該檔案中加入如下配置,該配置指定上步驟中定義的配置類為自動裝配的配置。(筆者努力最近把自動裝配的部落格寫出來)

1 #-------starter自動裝配---------
2 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.starter.config.DemoConfig

 7、測試

在demo-spring-boot-starter工程中執行mvn clean install 一個自定義的starter新鮮出爐。

新建測試工程

引入starter依賴

1         <dependency>
2             <groupId>com.demo</groupId>
3             <artifactId>demo-spring-boot-starter</artifactId>
4             <version>0.0.1-RELEASE</version>
5         </dependency>

 

配置檔案

1 demo.isopen=true
2 demo.say-what=hello
3 demo.to-who=shf

 

然後寫個測試類。

 1 package com.example.test.controller;
 2 
 3 import com.demo.starter.service.DemoService;
 4 import org.springframework.web.bind.annotation.GetMapping;
 5 import org.springframework.web.bind.annotation.RestController;
 6 
 7 import javax.annotation.Resource;
 8 
 9 /**
10  * 描述:
11  *
12  * @Author shf
13  * @Description TODO
14  * @Date 2019/5/13 15:52
15  * @Version V1.0
16  **/
17 @RestController
18 public class DemoController {
19     @Resource(name = "demo")
20     private DemoService demoService;
21 
22     @GetMapping("/say")
23     public String sayWhat(){
24         return demoService.say();
25     }
26     
27 }

 

 瀏覽器

 

相關文章