springboot 自定义starter类
不論在工作中,亦或是求職面試,Spring Boot已經成為我們必知必會的技能項,如今的各行各業都在飛速的擁抱這個已經不是很新的Spring啟動框架。
當然,作為Spring Boot的精髓,自動配置原理的工作過程往往只有在“面試”的時候才能用得上,但是如果在工作中你能夠深入的理解Spring Boot的自動配置原理,將無往不利。
Spring Boot的出現,得益于“習慣優于配置”的理念,沒有繁瑣的配置、難以集成的內容(大多數流行第三方技術都被集成),這是基于Spring 4.x提供的按條件配置Bean的能力。
自動配置原理
Spring Boot關于自動配置的源碼在spring-boot-autoconfigure-x.x.x.x.jar中:
當然,自動配置原理的相關描述,官方文檔貌似是沒有提及。不過我們不難猜出,Spring Boot的啟動類上有一個@SpringBootApplication注解,這個注解是Spring Boot項目必不可少的注解。那么自動配置原理一定和這個注解有著千絲萬縷的聯系!
@EnableAutoConfiguration
?@SpringBootApplication是一個復合注解或派生注解,在@SpringBootApplication中有一個注解@EnableAutoConfiguration,翻譯成人話就是開啟自動配置,其定義如下:
?而這個注解也是一個派生注解,其中的關鍵功能由@Import提供,其導入的AutoConfigurationImportSelector的selectImports()方法通過SpringFactoriesLoader.loadFactoryNames()掃描所有具有META-INF/spring.factories的jar包。spring-boot-autoconfigure-x.x.x.x.jar里就有一個這樣的spring.factories文件。
這個spring.factories文件也是一組一組的key=value的形式,其中一個key是EnableAutoConfiguration類的全類名,而它的value是一個xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔,如下圖所示:
這個@EnableAutoConfiguration注解通過@SpringBootApplication被間接的標記在了Spring Boot的啟動類上。在SpringApplication.run(...)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然后將所有自動配置類加載到Spring容器中。
自動配置生效
每一個XxxxAutoConfiguration自動配置類都是在某些條件之下才會生效的,這些條件的限制在Spring Boot中以注解的形式體現,常見的條件注解有如下幾項:
@ConditionalOnBean:當容器里有指定的bean的條件下。
@ConditionalOnMissingBean:當容器里不存在指定bean的條件下。
@ConditionalOnClass:當類路徑下有指定類的條件下。
@ConditionalOnMissingClass:當類路徑下不存在指定類的條件下。
@ConditionalOnProperty:指定的屬性是否有指定的值,比如@ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表當xxx.xxx為enable時條件的布爾值為true,如果沒有設置的情況下也為true。
以ServletWebServerFactoryAutoConfiguration配置類為例,解釋一下全局配置文件中的屬性如何生效,比如:server.port=8081,是如何生效的(當然不配置也會有默認值,這個默認值來自于org.apache.catalina.startup.Tomcat)。
在ServletWebServerFactoryAutoConfiguration類上,有一個@EnableConfigurationProperties注解:開啟配置屬性,而它后面的參數是一個ServerProperties類,這就是習慣優于配置的最終落地點。
在這個類上,我們看到了一個非常熟悉的注解:@ConfigurationProperties,它的作用就是從配置文件中綁定屬性到對應的bean上,而@EnableConfigurationProperties負責導入這個已經綁定了屬性的bean到spring容器中(見上面截圖)。那么所有其他的和這個類相關的屬性都可以在全局配置文件中定義,也就是說,真正“限制”我們可以在全局配置文件中配置哪些屬性的類就是這些XxxxProperties類,它與配置文件中定義的prefix關鍵字開頭的一組屬性是唯一對應的。
至此,我們大致可以了解。在全局配置的屬性如:server.port等,通過@ConfigurationProperties注解,綁定到對應的XxxxProperties配置實體類上封裝為一個bean,然后再通過@EnableConfigurationProperties注解導入到Spring容器中。
而諸多的XxxxAutoConfiguration自動配置類,就是Spring容器的JavaConfig形式,作用就是為Spring 容器導入bean,而所有導入的bean所需要的屬性都通過xxxxProperties的bean來獲得。
可能到目前為止還是有所疑惑,但面試的時候,其實遠遠不需要回答的這么具體,你只需要這樣回答:
Spring Boot啟動的時候會通過@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自動配置類,并對其進行加載,而這些自動配置類都是以AutoConfiguration結尾來命名的,它實際上就是一個JavaConfig形式的Spring容器配置類,它能通過以Properties結尾命名的類中取得在全局配置文件中配置的屬性如:server.port,而XxxxProperties類是通過@ConfigurationProperties注解與全局配置文件中對應的屬性進行綁定的。
什么是starter
Starter可以理解為一個可拔插式的插件,提供一系列便利的依賴描述符,您可以獲得所需的所有Spring和相關技術的一站式服務。應用程序只需要在maven中引入starter依賴,SpringBoot就能自動掃描到要加載的信息并啟動相應的默認配置。用一句話描述,就是springboot的場景啟動器。
下面是Spring官方提供的部分starter,全部的請參考官網:
?
自定義starter
官方定義的starter命名都是spring-boot-starter-xxx,我們自己定義的一般都 xxx-spring-boot-starter,新建一個id-gengerate-spring-boot-starter項目
導入springboot 包spring-boot-starter
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--主要是為了生成spring-configration-metadata.json文件,方便idea跳轉--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></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></dependencies>1.創建配置類,定義一個映射配置新的的類IdProperties和LockieProperties,添加注解ConfigurationProperties("machine.id"),我們的配置文件以machine.id開頭,比如mathine.id.name=boot-order,另外一個配置文件是已spring.lockie開頭的配置文件
package com.lockie.starter.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties;/*** @author: lockie* @Date: 2020/11/3 15:10* @Description: id生成配置類*/ @Data @ConfigurationProperties("machine.id") public class IdProperties {private String name; }package com.lockie.starter.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties;/*** @author: 鄒細良* @Date: 2020/11/3 18:21* @Description:*/ @Data @ConfigurationProperties("spring.lockie") public class LockieProperties {private String prefix;private String suffix; }2.創建一個接口用來生成對應的業務,IdService里面有個getId方法用來生成自定義的ID
package com.lockie.starter.service;import com.lockie.starter.config.IdProperties; import lombok.Data;/*** @author: lockie* @Date: 2020/11/3 15:19* @Description: 生成ID接口*/ @Data public class IdService {private IdProperties idProperties;/*** 獲取ID* @return*/public String getId() {return idProperties.getName() + "-" + System.currentTimeMillis();} }package com.lockie.starter.service;import com.lockie.starter.config.LockieProperties; import lombok.Data;/*** @author: lockie* @Date: 2020/11/3 18:23* @Description:*/ @Data public class LockieService {LockieProperties lockieProperties;public String hello(String name) {return lockieProperties.getPrefix() + "-" + name + "-" + lockieProperties.getSuffix();} }3.創建配置類,重要的配置參數
@Configuration:配置類
@EnableConfigurationProperties():開啟某屬性類,里面封裝的是屬性信息,相當于@ConfigurationProperties加載application.properties里面的信息,并用@Component將類交由spring管理
@ConditionalOnClass():當這個類存在時,再進行下面的步驟,否則就不進行下面的步驟了
@AutoConfigureAfter():當自動配置完成后,再執行里面的類
@ConfigurationOnMissBean():當這個bean不存在時,再添加bean類
@Bean:添加bean類
4.最重要的一步,在resources目錄下創建META-INF目錄,并添加文件spring.factories。在這個文件中配置EnableAutoConfiguration,具體如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.lockie.starter.config.IdAutoConfiguation,\com.lockie.starter.config.LockieAutoConfiguration測試自定義的Starter?
我們在之前的項目boot-order-service中測試我們的starter, boot-order-service項目pom增加id-generate-spring-boot-starter包
<dependency><groupId>com.lockie-starter</groupId><artifactId>id-generate-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>項目包路徑一樣可能還需要在boot-order-starter啟動類上增加掃描id-generate-spring-boot-starter項目包路徑?
@SpringBootApplication(scanBasePackages = "com.lockie.starter")boot-order-service項目配置文件增加配置參數
machine.id.name=boot-order spring.lockie.prefix=Hello! spring.lockie.suffix=Nice to meet you到這里我們在boot-order-service服務中就可以使用id-generate-spring-boot-starter項目中的services了,并且只需要使用@Autowired即可
@SpringBootTest @ContextConfiguration(classes = BootOrderServiceApplication.class) class BootOrderServiceApplicationTests {@Testvoid contextLoads() {}@AutowiredIdService idService;@AutowiredLockieService lockieService;@Testpublic void testIdGenerate() {String id = idService.getId();System.out.println("生成ID:" + id);String str = lockieService.hello("小明");System.out.println("打招呼:"+ str);} }運行一下查看結果,看到結果是我們想要的,至此我們自定義一個starter就成功了,總結一下就是要創建3個類1個配置文件,xxProperties,xxService,xxAutoConfiguation和spring.factories
總結
以上是生活随笔為你收集整理的springboot 自定义starter类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读书笔记:时间与精力管理:你的精力管理决
- 下一篇: 流氓软件,终于被爆出来了