Spring Boot -- Spring Boot Starter的簡單實現
一、什麼是Spring Boot Starter
1.1 自動裝配
在介紹Spring Boot Starter之前,我們需要了解一下Spring Boot的自動裝配機制,因為Spring Boot Starter的實現依賴於Spring Boot的自動裝配機制。
SpringBoot在程式初始化時可以根據classpath、property屬性、context中例項、以及執行容器特徵等各種動態條件,來按需初始化相應的bean,並註冊到IOC容器中。
SpringBoot啟動的時候通過@EnableAutoConfiguration註解找到META-INF/spring.factories配置檔案中所有的自動配置類,並對其進行載入,而這些自動配置類的類名都是以AutoConfiguration結尾來命名的,它實際上就是一個javaConfig形式的Spring容器配置類,它們都有一個@EnableConfigurationPerperties的註解,通過這個註解啟動XXXProperties命名的類去載入全域性配置中的屬性,如server.port,而XXXProperties通過@ConfigurationProperties註解將全域性配置檔案中的屬性與自己的屬性進行繫結。
1.2 Spring Boot Starter概念
Starter是SpringBoot中的一個非常重要的概念,Starter相當於模組,它能將模組所需的依賴整合起來並對模組內的Bean根據環境(條件)進行自動裝配。使用者只需要依賴相應功能的Starter,無需做過多的配置和依賴,SpringBoot就能自動掃描並載入相應的模組。
Spring Boot Starter它提供了一個自動化配置類,一般命名為 XXXAutoConfiguration ,在這個配置類中通過條件註解來決定一個配置是否生效;然後,它還會提供一系列的預設配置,也允許開發者根據實際情況自定義相關配置;最後,通過型別安全的屬性注入將這些配置屬性注入進來,新注入的屬性會代替掉預設屬性。
例如,如果想使用Spring和JPA訪問資料庫,只需要專案中包含spring-boot-starter-data-jpa 依賴項,就可以正常使用。已有的Spring Boot Starter有很多,常用的有:
- spring-boot-starter:核心 starter,包括自動化配置支援,日誌以及 YAML
- spring-boot-starter-test:SpringBoot 測試相關的 starter
- spring-boot-starter-web:構建 restful、springMVC 的 web應用程式的 starter
- spring-boot-starter-security:使用 Spring Security 的 starter
二、Spring Boot Starter編寫
2.1 編寫步驟
編寫Starter非常簡單,與編寫一個普通的Spring Boot應用沒有太大區別:
- 新建Maven專案,在專案的POM檔案中定義使用的依賴;
- 新建配置類,寫好配置項和預設的配置值,指明配置項字首;
- 新建自動裝配類,根據 @Conditional註解的條件,使用@Configuration和@Bean來進行自動裝配;
- 新建spring.factories檔案,指定Starter的自動裝配類;
- 編寫服務類,也就是我們starter要實現的功能;
2.2 案例
新建maven專案,配置pom檔案:
<?xml version="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.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-starter-helloworld</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<!-- 核心 starter,包括自動化配置支援,日誌以及 YAML -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 其中 spring-boot-configuration-processor 的作用是編譯時生成 spring-configuration-metadata.json ,
此檔案主要給IDE使用。如當配置此jar相關配置屬性在 application.yml ,你可以用ctlr+滑鼠左鍵點選屬性名,IDE會跳轉
到你配置此屬性的類中。 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- spring boot 測試相關的 starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
View Code
這裡順帶提一下spring-boot-stater-parent,
spring-boot-starter-parent 主要有如下作用:
- 定義了 Java 編譯版本。
- 使用 UTF-8 格式編碼。
- 繼承自 spring-boot-dependencies,這個裡邊定義了依賴的版本,也正是因為繼承了這個依賴,所以我們在寫依賴時才不需要寫版本號。
- 執行打包操作的配置。
- 自動化的資源過濾。
- 自動化的外掛配置。
- 針對 application.properties 和 application.yml 的資源過濾,包括通過 profile 定義的不同環境的配置檔案,例如 application-dev.properties 和 application-dev.yml。
新建配置類HelloWorldProperties.java:
package com.goldwind.example;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 新建配置類,寫好配置項和預設的配置值,指明配置項字首
*
* @author zy
* @since 2021/9/22
*/
@Data
@ConfigurationProperties(prefix = "example")
public class HelloWorldProperties {
// 姓名
private String name = "zy";
// 年齡
private Integer age = 18;
}
新建自動裝配類HelloWorldAutoConfiguration.java:
package com.goldwind.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 新建自動裝配類,使用@Configuration和@Bean來進行自動裝配
*
* @author zy
* @since 2021/9/22
*/
@Configuration
@ConditionalOnClass(HelloWorldService.class)
@EnableConfigurationProperties(HelloWorldProperties.class)
public class HelloWorldAutoConfiguration {
@Autowired
private HelloWorldProperties properties;
@Bean
@ConditionalOnMissingBean
public HelloWorldService starterService() {
return new HelloWorldService(properties);
}
}
新建spring.factories(resources/META-INF路徑下):
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.goldwind.example.HelloWorldAutoConfiguration
編寫服務類HelloWorldService.java:
package com.goldwind.example;
/**
* 編寫服務類,也就是我們starter要實現的功能
* 輸出配置檔案中的資訊
*
* @author zy
* @since 2021/9/22
*/
public class HelloWorldService {
private HelloWorldProperties properties;
/**
* 建構函式
*/
public HelloWorldService(HelloWorldProperties properties) {
this.properties = properties;
}
public void helloWorld() {
System.out.println(String.format("我的名字是%s,我今年%d歲", properties.getName(), properties.getAge()));
}
}
執行mvn install,生成spring-boot-starter-helloworld.jar。
三、引用Starter
3.1 步驟
- 將Starter專案的依賴新增到我們自己的spring boot專案中;
- 在application.yml配置檔案中新增配置資訊;
3.2 案例
新建maven專案,配置pom檔案:
<?xml version="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.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
新建DemoRunner.java:
package com.goldwind.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 通過實現ApplicationRunner或CommandLineRunner介面,可以實現應用程式啟動完成後自動執行run方法
*
* @author zy
* @since 2021/9/22
*/
@Component
public class DemoRunner implements ApplicationRunner {
@Autowired
private HelloWorldService helloWorldService;
@Override
public void run(ApplicationArguments args) throws Exception {
helloWorldService.helloWorld();
}
}
新建DemoApplication.java:
package com.goldwind.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
修改配置檔案application.yml:
example:
name: sf
age: 28