SpringBoot起飛系列-自定義starter(十)


一、前言


到現在,我們可以看出來,如果我們想用一些功能,基本上都是通過添加spring-boot-starter的方式來使用的,因為各種各樣的功能都被封裝成了starter,然后把相關服務注入到容器中去,那么如果我們想用一下自己的某些功能呢,那就也要編寫一個自定義的starter,所以今天我們就來看看,怎么編寫自己的starter,來實現在springboot中實現自己想要的一些功能。


二、原理


回想一下, 當我們使用一個官方的starter的時候,只需要將相應的starter依賴包添加到pom.xml中去就可以了,然后maven自動下載依賴包,並且springboot在啟動后會自動配置相關的服務,然后注入的到容器中去。那么springboot是如何知道要去調用哪些方法,加載哪些配置,並注入哪些bean呢?


基本步驟如下:


1.首先,springboot在啟動的時候會去找starter包下resources/META-INF/spring.factories文件,然后根據文件中配置的自動配置類運行,加載autoconfigure類。


2.根據@Conditional注解的條件,決定Bean是否要注入的容器中去。


3.然后我們一般用的就是這個Bean,來使用其中的一些功能。


三、編寫自己的Starter


3.1 創建maven項目


首先我們創建一個maven項目,按照如下名字起名,其實starter說白了也只是一個jar:



一般的,官方的starter命名方式是spring-boot-start-xxx的形式,為了區分,我們自定義的starter用xxx-spring-boot-starter的命名方式。


1.添加springboot的依賴,因為要成為一個spring-boot-starter是需要依賴springboot的這套流程的,所以我們引入以下依賴:



 1 <project xmlns='http://maven.apache.org/POM/4.0.0'
2 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
6 <groupId>com.example.demo</groupId>
7 <artifactId>person-spring-boot-starter</artifactId>
8 <version>1.0-SNAPSHOT</version>
9 <packaging>jar</packaging>
10
11 <dependencies>
12 <dependency>
13 <groupId>org.springframework.boot</groupId>
14 <artifactId>spring-boot-autoconfigure</artifactId>
15 <version>2.0.0.RELEASE</version>
16 </dependency>
17 <dependency>
18 <groupId>org.springframework.boot</groupId>
19 <artifactId>spring-boot-configuration-processor</artifactId>
20 <version>2.0.0.RELEASE</version>
21 <optional>true</optional>
22 </dependency>
23 </dependencies>
24
25 </project>


2.添加配置類PersonProperties,主要來從配置文件中讀取配置綁定到這個類上:



 1 package com.example.demo;
2
3 import org.springframework.boot.context.properties.ConfigurationProperties;
4
5 @ConfigurationProperties(prefix = 'spring.person')
6 public class PersonProperties {
7 private String name;
8
9 private Integer age;
10
11 public String getName() {
12 return name;
13 }
14
15 public void setName(String name) {
16 this.name = name;
17 }
18
19 public Integer getAge() {
20 return age;
21 }
22
23 public void setAge(Integer age) {
24 this.age = age;
25 }
26 }


3.添加我們的核心服務類,這里邊是我們主要提供的功能,假設我們提供了一個sayHello方法,返回一段話:



 1 package com.example.demo;
2
3 public class PersonService {
4 private PersonProperties personProperties;
5
6 public PersonService(PersonProperties personProperties) {
7 this.personProperties = personProperties;
8 }
9 public String sayHello() {
10 return '大家好,我叫: ' + personProperties.getName() + ', 今年' + personProperties.getAge() + '歲';
11 }
12 }


4.添加自動配置類,這個類主要是給springboot來用的,springboot會用這個類來啟動,激活我們的服務,注冊都容器中去:



 1 @Configuration
2 @EnableConfigurationProperties(PersonProperties.class)
3 @ConditionalOnClass(PersonService.class)
4 @ConditionalOnProperty(prefix = 'spring.person', value = 'enabled', matchIfMissing = true)
5 public class PersonServiceAutoConfiguration {
6 @Autowired
7 private PersonProperties personProperties;
8
9 @Bean
10 public PersonService personService(){
11 return new PersonService(personProperties);
12 }
13 }


解釋一下代碼中用到的幾個注解:



  • @ConditionalOnClass,當classpath下發現該類的情況下進行自動配置。

  • @ConditionalOnMissingBean,當Spring Context中不存在該Bean時。

  • @ConditionalOnProperty(prefix = 'srping.person',value = 'enabled',havingValue = 'true'),當配置文件中spring.perons.enabled=true時。如果沒有,使用matchIfMissing的值,也為true。

  • @Bean,把返回的PersonService對象添加的spring容器中去,這樣我們再使用的使用就可以直接裝配了。


其他注解:



  • @ConditionalOnBean:當容器中有指定的Bean的條件下

  • @ConditionalOnClass:當類路徑下有指定的類的條件下

  • @ConditionalOnExpression:基於SpEL表達式作為判斷條件

  • @ConditionalOnJava:基於JVM版本作為判斷條件

  • @ConditionalOnJndi:在JNDI存在的條件下查找指定的位置

  • @ConditionalOnMissingBean:當容器中沒有指定Bean的情況下

  • @ConditionalOnMissingClass:當類路徑下沒有指定的類的條件下

  • @ConditionalOnNotWebApplication:當前項目不是Web項目的條件下

  • @ConditionalOnProperty:指定的屬性是否有指定的值

  • @ConditionalOnResource:類路徑下是否有指定的資源

  • @ConditionalOnSingleCandidate:當指定的Bean在容器中只有一個,或者在有多個Bean的情況下,用來指定首選的Bean

  • @ConditionalOnWebApplication:當前項目是Web項目的條件下


 5. 在resources下添加spring.factories文件,目錄結構如下/resources/META-INF/spring.factories,springboot會自動識別這個文件,加載運行我們的PersonServiceAutoConfiguration類。



6.編譯運行,用maven install安裝jar,默認會安裝的maven的倉庫里邊,用於后來我們使用。



3.2 創建springboot項目測試


這一步簡單就不說了,直接按模板創建一個springboot的web項目就行了,然后我們在pom.xml中添加我們剛才寫好的person-spring-boot-starter:



1  <dependency>
2 <groupId>com.example.demo</groupId>
3 <artifactId>person-spring-boot-starter</artifactId>
4 <version>1.0-SNAPSHOT</version>
5 </dependency>


配置文件中添加starter的配置項:



spring.person.age=12
spring.person.name
=songlin


添加一個控制器測試:



 1 @RestController
2 public class HelloController {
3
4 @Autowired
5 PersonService personService;
6
7 @GetMapping('/hello')
8 public String hello(){
9 String s = personService.sayHello();
10 return s;
11 }
12 }


訪問http://localhost:8080/hello,顯示如下:



四、總結


當我們想往springboot集成一個功能的時候,就可以用這種方式了,關於starter的寫法,大家還可以參看源碼,理解了源碼我們就能寫出更好用的starter了。springboot的基本入門系列就先到這了,往后我們就開始學習springboot集成高級功能了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM