SpringBoot(04)——建立自己的自動配置
建立自己的自動配置
當你的應用需要以jar包的形式提供給其它應用使用時,可以考慮把它們封裝為一個Spring Boot Starter。即該jar包是可以自動新增需要引用的依賴項,也能夠對核心功能進行自動配置。自動配置的核心類是一個標註了@Configuration
的類,然後在自動配置類中可以定義相應的bean。比如下面的配置類中定義了一個HelloBean型別的bean。
@Configuration
public class HelloAutoConfiguration {
@Bean
public HelloBean helloBean() {
return new HelloBean();
}
}
然後需要在Classpath下的META-INF/spring.factories
中以org.springframework.boot.autoconfigure.EnableAutoConfiguration
為Key,以對應的自動配置類為Value進行配置,如果有多個自動配置類,多個自動配置類之間可以以英文逗號分隔。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.elim.autoconfigure.HelloAutoConfiguration
Spring Boot在啟動時將讀取Classpath下META-INF/spring.factories
中Key為org.springframework.boot.autoconfigure.EnableAutoConfiguration
的配置類,將它們進行例項化。所以經過上述配置後,系統啟動後將自動建立HelloBean型別的bean。
自動配置類通常不會像上面那樣直接進行定義,而是會新增一些附加條件,比如在Classpath中擁有某些Class才生效,或者需要bean容器中不存在指定bean時才生效等等。Spring Boot為它們提供了一系列的@ConditionalXXX
,常用的如下:
- ConditionalOnClass :用於指定在Classpath下擁有某些Class時才生效
- ConditionalOnMissingClass :用於指定在Classpath下不存在某些Class時才生效
- ConditionalOnBean :用於指定在bean容器中存在某些bean時生效
- ConditionalOnMissingBean :用於指定在bean容器中不存在某些bean時生效
- ConditionalOnWebApplication :用於指定當應用是Web應用時生效
- ConditionalOnNotWebApplication :用於指定當應用是非Web應用時生效
- ConditionalOnProperty :用於指定當配置了某些特定的引數時生效
- ConditionalOnExpression :用於根據SpEl表示式控制是否生效
- ConditionalOnSingleCandidate :用於指定當bean容器中只存在唯一的指定型別的bean時才生效;當bean容器中存在多個指定型別的bean,但是使用
@Primary
指定了主候選者也是可以匹配的,即也是生效的
更多可用的Conditional註解可以參考API文件的
org.springframework.boot.autoconfigure.condition
包。
下面的程式碼中指定了當Classpath下存在Hello.class,且bean容器中不存在HelloBean型別的bean時下面的配置類將生效。
@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {
@Bean
public HelloBean helloBean() {
return new HelloBean();
}
}
這些條件配置註解也是可以新增到bean上的。比如下面程式碼中指定了當Environment中存在Key為autoconfigure.hello.enabled
屬性且其值為true時將建立HelloBean型別的bean,或者當Environment中不存在Key為autoconfigure.hello.enabled
屬性時也將建立HelloBean型別的bean(由matchIfMissing控制)。所以針對下面的配置,預設情況下是會建立HelloBean型別的bean的,如果不期望建立該型別的bean,可以在application.properties檔案中指定autoconfigure.hello.enabled=false
。
@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {
@Bean
@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", havingValue = "true", matchIfMissing = true)
public HelloBean helloBean() {
return new HelloBean();
}
}
當使用@ConditionalOnProperty時如果對應的值的可選值是true/false,可以不指定havingValue屬性,此時只要值不為false,都會認為是true。
繫結引數
通常自定義的Starter會需要依靠外部配置的屬性進行一些自動配置。此時可以使用@ConfigurationProperties
標註在用來接收屬性的Class上,它可以指定一個字首,然後將在application.properties中尋找指定字首和欄位名稱組合起來的屬性進行繫結。比如下面的屬性類中的name屬性將繫結application.properties中定義的autoconfigure.hello.name
屬性的值。
@Data
@ConfigurationProperties("autoconfigure.hello")
public class HelloProperties {
private String name;
private String message;
}
@ConfigurationProperties
標註的Class需要通過在配置類上使用@EnableConfigurationProperties
進行啟用。@EnableConfigurationProperties
指定的配置類會自動註冊為Spring bean容器中的一個bean,然後可以在配置類中自動注入對應的屬性類。比如下面的程式碼中在HelloAutoConfiguration類上通過@EnableConfigurationProperties(HelloProperties.class)
指定了啟用HelloProperties這個屬性配置類,然後把它定義為HelloAutoConfiguration類中的一個屬性,並標註為自動注入,然後在定義HelloBean型別的bean時從HelloProperties中獲取屬性值進行配置。
@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
@Autowired
private HelloProperties helloProperties;
@Bean
@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)
public HelloBean helloBean() {
HelloBean helloBean = new HelloBean();
helloBean.setName(helloProperties.getName());
return helloBean;
}
}
上面的程式碼中定義HelloBean時從HelloProperties中獲取name屬性賦值給了HelloBean物件的name屬性。這樣的需求其實可以直接通過@ConfigurationProperties
給HelloBean的name屬性賦值,而不必新增多餘的HelloProperties類。把@ConfigurationProperties
定義在HelloBean定義的方法上可以擁有相同的效果,比如下面這樣。
@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {
@Bean
@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)
@ConfigurationProperties("autoconfigure.hello")
public HelloBean helloBean() {
return new HelloBean();
}
}
使用
@ConfigurationProperties
定義屬性配置類時最好定義的字首不要以spring開頭,以免跟未來Spring官方提供的屬性配置類存在衝突。自定義的Starter在命名時不要命名為
spring-boot-starter-xxx
,可以命名為xxx-spring-boot-starter
。spring-boot-starter-xxx
留給官方使用。
參考文件
(注:本文基於Spring Boot 2.0.3所寫)
相關文章
- 如何實現自己的SpringBoot自動配置Spring Boot
- SpringBoot-04-自動配置原理再理解Spring Boot
- 建立屬於自己的 Spring Boot 自動配置Spring Boot
- SpringBoot的自動配置Spring Boot
- SpringBoot的自動配置原理Spring Boot
- SpringBoot(03)——自動配置Spring Boot
- SpringBoot | 自動配置原理Spring Boot
- SpringBoot(二)自動配置Spring Boot
- springboot 自動配置原理Spring Boot
- Springboot MVC 自動配置Spring BootMVC
- SpringBoot自動配置原理Spring Boot
- SpringBoot | 4.1 SpringMVC的自動配置Spring BootSpringMVC
- springboot web專案建立及自動配置分析(thymeleaf+flyway)Spring BootWeb
- springboot_自動配置原理Spring Boot
- springboot 自動配置案例分析Spring Boot
- SpringBoot入門(四)——自動配置Spring Boot
- SpringBoot自動配置原理解析Spring Boot
- springboot自動配置原理和啟動流程Spring Boot
- 讓SpringBoot自動化配置不再神祕Spring Boot
- SpringBoot整合Nacos自動重新整理配置Spring Boot
- springboot 配置熱啟動 不需重啟自動部署Spring Boot
- 全網最深分析SpringBoot MVC自動配置失效的原因Spring BootMVC
- 圖解原始碼 | SpringBoot中自動配置原理圖解原始碼Spring Boot
- SpringBoot——自定義自動配置與起步依賴Spring Boot
- SpringBoot自動配置原理原始碼級別分析Spring Boot原始碼
- SpringBoot原始碼解析-Bean的載入與自動化配置Spring Boot原始碼Bean
- SpringBoot配置檔案及自動配置原理詳解,這應該是SpringBoot最大的優勢了吧Spring Boot
- springboot擴充套件配置檔案自動載入Spring Boot套件
- Spring-04 Bean的自動裝配SpringBean
- 笑死,面試官又問我SpringBoot自動配置原理面試Spring Boot
- SpringBoot 自動配置原理,翻原始碼看一下Spring Boot原始碼
- Springboot專案啟動後自動建立多表關聯的資料庫與表的方案Spring Boot資料庫
- Springboot實現基於字首的自定義配置和自動提示功能Spring Boot
- 這一次搞懂SpringBoot核心原理(自動配置、事件驅動、Condition)Spring Boot事件
- Spring Boot自動配置原理懂後輕鬆寫一個自己的starterSpring Boot
- 小BUG大原理:重寫WebMvcConfigurationSupport後SpringBoot自動配置失效WebMVCSpring Boot
- 自己手動建立https證書HTTP
- SpringBoot | 2.1 SpringBoot自動裝配原理Spring Boot