javascript
Spring Boot(04)——创建自己的自动配置
創建自己的自動配置
當你的應用需要以jar包的形式提供給其它應用使用時,可以考慮把它們封裝為一個Spring Boot Starter。即該jar包是可以自動添加需要引用的依賴項,也能夠對核心功能進行自動配置。自動配置的核心類是一個標注了@Configuration的類,然后在自動配置類中可以定義相應的bean。比如下面的配置類中定義了一個HelloBean類型的bean。
@Configuration public class HelloAutoConfiguration {@Beanpublic 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.HelloAutoConfigurationSpring 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 {@Beanpublic 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 {@Autowiredprivate 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留給官方使用。
參考文檔
https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/html/boot-features-developing-auto-configuration.html
(注:本文基于Spring Boot 2.0.3所寫)
總結
以上是生活随笔為你收集整理的Spring Boot(04)——创建自己的自动配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么我要放弃javaScript数据结
- 下一篇: Spring Developer Too