筆者語錄: 話不多說,直接開幹。
spring-boot-starter的關鍵:
@SpringBootApplication註解源碼是這樣的:
@ComponentScan註解的作用是把(@SpringBootApplication所在的)入口類所在的包(及其子包)下的所有被@Component註解(或拓展了@Component的註解)標記了的bean註冊到spring容器中
。那麼,處於@ComponentScan掃描範圍外的bean是
如何註冊到容器中的呢,那就是靠@EnableAutoConfiguration來實現註冊的
。
@EnableAutoConfiguration註解的作用是:將普通jar包資源目錄下的META-INF/spring.factories文件裏面配置的鍵爲org.springframework.boot.autoconfigure.EnableAutoConfiguration的類納入考慮範圍內,考慮是否將這個(些)類註冊進Spring容器。如果這個(些)類被@Component註解(或拓展了@Component的註解)標記了,且滿足@Conditional…條件(如果有@Conditional…的話),那麼將其註冊進Spring容器,如果不滿足條件,那麼就不註冊進Spring容器。
- 注:追蹤源碼可知,在@EnableAutoConfiguration註解裏面啓用了
SpringBoot的
AutoConfigurationImportSelector類, 在AutoConfigurationImportSelector類中的getAutoConfigurationEntry
方法裏,調用了Spring的SpringFactoriesLoader#loadFactories
來加載資源jar包下的META-INF/spring.factories
文件裏的key爲org.springframework.boot.autoconfigure.EnableAutoConfiguration的value集合
。 - 注:@Conditional…條件有:
編寫spring-boot-starter(示例):
提示: artifactId的命名需要注意,spring-boot-starter-xxx是SpringBoot官方保留
的starter命名方式;業界
自定義的starter的命名,一般用xxx-spring-boot-starter
。
第一步:創建一個SpringBoot項目,並簡單改造。
- 在pom.xml中引入spring-boot-configuration-processor和spring-boot-autoconfigure(
完整pom.xml見下方
)。 - 去掉pom.xml中的打可執行的jar包的插件(
完整pom.xml見下方
)。
注:普通的jar包與可執行的jar包的class文件路徑是不一樣的。
注:只要去掉這個打包插件就行;去不去掉SpringBoot的啓動類都沒關係,不過出於潔癖考慮,推薦同時去掉啓動類。
注:這裏 給出完整的pom.xml:<?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.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pingan</groupId> <artifactId>custom-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>custom-spring-boot-starter</name> <description>編寫spring-boot-starter</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> </project>
第二步:編寫“管理”類。這個類用來管理:啓用哪些被@ConfigurationProperties標記了的類、註冊哪些Bean等等。
import com.pingan.customstarter.service.LogicHandler;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* starter管理類
*
* @author JustryDeng
* @date 2020/4/4 14:48:27
*/
@Configuration
@EnableConfigurationProperties(CustomAutoConfiguration.Properties.class)
@ConditionalOnProperty(value = "coder.info.enabled", havingValue = "true")
public class CustomAutoConfiguration {
@Bean
public LogicHandler logicHandler() {
return new LogicHandler();
}
/**
* 配置信息
*
* @author JustryDeng
* @date 2020/4/4 14:38:05
*/
@Setter
@Getter
@ConfigurationProperties(prefix = "coder.info")
public static class Properties {
/** 是否啓用 */
private boolean enabled = false;
/** 姓名 */
private String name;
/** 愛好 */
private String motto;
}
}
注:這個管理類不是必須的
。如果不創建這個管理類來統一管理那些可能需要註冊進容器的類的話,那麼就需要在第四步(見下文)的spring.factories文件裏,指定這些類
了;無疑,創建管理類更方便,更利於維護。
第三步:編寫一個業務邏輯相關的類(見:第二步註冊進Spring的那個bean),用來做需要的邏輯。
第四步:在資源目錄下的META-INF/spring.factories文件(無則創建)裏,通過org.springframework.boot.autoconfigure.EnableAutoConfiguration指定要註冊進容器的類。
注:指定後,這個類不是說一定會被註冊進容器,其必須被@Component註解(或拓展了@Component的註解)標記了,並且如果其有@Conditional…條件的話,那麼還需要滿足條件,纔會被註冊進Spring容器。
注:如果需要註冊多個類,那麼使用逗號隔開,如:
第五步:mvn install到本地倉庫(,mvn deploy到遠程倉庫),供其它項目使用。
測試一下:
- 第一步: 創建一個新的SpringBoot項目,並在pom.xml中,引入我們編寫的starter。
- 第二步: 在application.yml中配置參數,使觸發啓動starter中的配置類。
- 第三步: 編寫測試代碼,並測試。
- 啓動項目,控制檯輸出:
由此可見,自定義spring-boot-starter成功!
^_^ 如有不當之處,歡迎指正
^_^ 參考鏈接
https://www.cnblogs.com/yuansc/p/9088212.html
https://www.cnblogs.com/softidea/p/6886460.html
https://blog.csdn.net/SkyeBeFreeman/article…
^_^ 參考資料
《Spring Boot Cookbook》
^_^ 測試代碼託管鏈接
https://github.com/JustryDeng/…spring-boot-starter…
^_^ 本文已經被收錄進《程序員成長筆記(二)》,筆者JustryDeng