摘要:代碼如下所示自定義業務實現恒宇少年碼云消息內容是否顯示消息內容,我們內的代碼比較簡單,根據屬性參數進行返回格式化后的字符串。
在我們學習SpringBoot時都已經了解到starter是SpringBoot的核心組成部分,SpringBoot為我們提供了盡可能完善的封裝,提供了一系列的自動化配置的starter插件,我們在使用spring-boot-starter-web時只需要在pom.xml配置文件內添加依賴就可以了,我們之前傳統方式則是需要添加很多相關SpringMVC配置文件。而spring-boot-starter-web為我們提供了幾乎所有的默認配置,很好的降低了使用框架時的復雜度。
因此在使用xx.starter時你就不用考慮該怎么配置,即便是有一些必要的配置在application.properties配置文件內對應配置就可以了,那好,為什么我在application.properties配置對應屬性后xx.starter就可以獲取到并作出處理呢?下面我們帶著這個疑問來編寫我們自定義的starter讓我們深入了解SpringBoot
自定義starter并且通過spring-boot-autoconfigure完成自動化配置。
構建項目創建starter項目我們并不需要創建SpringBoot項目,我們創建一個Maven項目就可以滿足我們的需求,創建項目完成后pom.xml配置信息如下所示:
4.0.0 com.yuqiyu chapter28 1.0.0 jar UTF-8 org.springframework.boot spring-boot-autoconfigure 1.5.4.RELEASE
我們這個starter并不做其他復雜邏輯的編寫,所以這里的依賴只是添加了spring-boot-autoconfigure,實戰開發時可以添加任意依賴到項目中。
配置映射參數實體我們在文章開頭埋下了一個疑問,starter是如何讀取application.properties或者application.yml配置文件內需要的配置參數的呢?那么接下來我們就看看如何可以獲取自定義的配置信息。
SpringBoot在處理這種事情上早就已經考慮到了,所以提供了一個注解@ConfigurationProperties,該注解可以完成將application.properties配置文件內的有規則的配置參數映射到實體內的field內,不過需要提供setter方法,自定義配置參數實體代碼如下所示:
package com.yuqiyu.chapter28; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 配置文件實體映射 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:51 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @ConfigurationProperties(prefix = "hello") public class HelloProperties { //消息內容 private String msg = "HengYu"; //是否顯示消息內容 private boolean show = true; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public boolean isShow() { return show; } public void setShow(boolean show) { this.show = show; } }
在上面代碼中,@ConfigurationProperties注解內我們使用到了屬性preffix,該屬性配置了讀取參數的前綴,根據上面的實體屬性對應配置文件內的配置則是hello.msg、hello.show,當然我們提供了默認值,配置文件內不進行配置時則是使用默認值。
編寫自定義業務我們為自定義starter提供一個Service,并且提供一個名為sayHello的方法用于返回我們配置的msg內容。代碼如下所示:
package com.yuqiyu.chapter28; /** * 自定義業務實現 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:54 * 碼云:http://git.oschina.net/jnyqy * ======================== */ public class HelloService { //消息內容 private String msg; //是否顯示消息內容 private boolean show = true; public String sayHello() { return show ? "Hello," + msg : "Hidden"; } public void setMsg(String msg) { this.msg = msg; } public void setShow(boolean show) { this.show = show; } }
我們Service內的代碼比較簡單,根據屬性參數進行返回格式化后的字符串。
接下來我們開始編寫自動配置,這一塊是starter的核心部分,配置該部分后在啟動項目時才會自動加載配置,當然其中有很多細節性質的配置
實現自動化配置自動化配置其實只是提供實體bean的驗證以及初始化,我們先來看看代碼:
package com.yuqiyu.chapter28; 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.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 自定義starter自動化配置 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:56 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @Configuration//開啟配置 @EnableConfigurationProperties(HelloProperties.class)//開啟使用映射實體對象 @ConditionalOnClass(HelloService.class)//存在HelloService時初始化該配置類 @ConditionalOnProperty//存在對應配置信息時初始化該配置類 ( prefix = "hello",//存在配置前綴hello value = "enabled",//開啟 matchIfMissing = true//缺失檢查 ) public class HelloAutoConfiguration { //application.properties配置文件映射前綴實體對象 @Autowired private HelloProperties helloProperties; /** * 根據條件判斷不存在HelloService時初始化新bean到SpringIoc * @return */ @Bean//創建HelloService實體bean @ConditionalOnMissingBean(HelloService.class)//缺失HelloService實體bean時,初始化HelloService并添加到SpringIoc public HelloService helloService() { System.out.println(">>>The HelloService Not Found,Execute Create New Bean."); HelloService helloService = new HelloService(); helloService.setMsg(helloProperties.getMsg());//設置消息內容 helloService.setShow(helloProperties.isShow());//設置是否顯示 return helloService; } }
自動化配置代碼中有很多我們之前沒有用到的注解配置,我們從上開始講解
@Configuration:這個配置就不用多做解釋了,我們一直在使用
@EnableConfigurationProperties:這是一個開啟使用配置參數的注解,value值就是我們配置實體參數映射的ClassType,將配置實體作為配置來源。
有關@ConditionalOnXxx相關的注解這里要系統的說下,因為這個是我們配置的關鍵,根據名稱我們可以理解為具有Xxx條件,當然它實際的意義也是如此,條件注解是一個系列,下面我們詳細做出解釋
@ConditionalOnBean:當SpringIoc容器內存在指定Bean的條件
@ConditionalOnClass:當SpringIoc容器內存在指定Class的條件
@ConditionalOnExpression:基于SpEL表達式作為判斷條件
@ConditionalOnJava:基于JVM版本作為判斷條件
@ConditionalOnJndi:在JNDI存在時查找指定的位置
@ConditionalOnMissingBean:當SpringIoc容器內不存在指定Bean的條件
@ConditionalOnMissingClass:當SpringIoc容器內不存在指定Class的條件
@ConditionalOnNotWebApplication:當前項目不是Web項目的條件
@ConditionalOnProperty:指定的屬性是否有指定的值
@ConditionalOnResource:類路徑是否有指定的值
@ConditionalOnSingleCandidate:當指定Bean在SpringIoc容器內只有一個,或者雖然有多個但是指定首選的Bean
@ConditionalOnWebApplication:當前項目是Web項目的條件
以上注解都是元注解@Conditional演變而來的,根據不用的條件對應創建以上的具體條件注解。
到目前為止我們還沒有完成自動化配置starter,我們需要了解SpringBoot運作原理后才可以完成后續編碼。
Starter自動化運作原理在注解@SpringBootApplication上存在一個開啟自動化配置的注解@EnableAutoConfiguration來完成自動化配置,注解源碼如下所示:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class>[] exclude() default {}; String[] excludeName() default {}; }
在@EnableAutoConfiguration注解內使用到了@import注解來完成導入配置的功能,而EnableAutoConfigurationImportSelector內部則是使用了SpringFactoriesLoader.loadFactoryNames方法進行掃描具有META-INF/spring.factories文件的jar包。我們可以先來看下spring-boot-autoconfigure包內的spring.factories文件內容,如下所示:
# Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer, org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer # Application Listeners org.springframework.context.ApplicationListener= org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener= org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter= org.springframework.boot.autoconfigure.condition.OnClassCondition # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration= org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration, org.springframework.boot.autoconfigure.aop.AopAutoConfiguration, .....省略
可以看到配置的結構形式是Key=>Value形式,多個Value時使用,隔開,那我們在自定義starter內也可以使用這種形式來完成,我們的目的是為了完成自動化配置,所以我們這里Key則是需要使用org.springframework.boot.autoconfigure.EnableAutoConfiguration
自定義spring.factories我們在src/main/resource目錄下創建META-INF目錄,并在目錄內添加文件spring.factories,具體內容如下所示:
#配置自定義Starter的自動化配置 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yuqiyu.chapter28.HelloAutoConfiguration
都目前為止我們的自定義starter已經配置完成,下面我們需要新建一個SpringBoot項目來測試我們的自動化配置是否已經生效。
創建測試SpringBoot項目在使用自定義starter之前需要將starter作Maven Jar Install到本地,我們使用idea工具自帶的maven命令完成該操作
步驟:工具右側 -> Maven Projects -> Lifecycle -> install
創建測試項目的pom.xml配置文件內容如下所示:
4.0.0 com.yuqiyu.sample test-spring-boot-starter-hello 0.0.1-SNAPSHOT jar test-spring-boot-starter-hello Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 1.5.4.RELEASE UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter com.yuqiyu chapter28 1.0.0 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin
我們只需要將依賴添加到pom.xml配置文件內
運行測試在運行項目之前,我們打開application.properties配置文件開啟debug模式,查看自動化配置的輸出日志,配置內容如下所示:
#顯示debug日志信息 debug=true
接下來我們啟動項目,在控制臺查找是否存在我們的HelloAutoConfiguration日志輸出,控制臺輸出內容如下所示:
.....省略 >>>The HelloService Not Found,Execute Create New Bean. .....省略 HelloAutoConfiguration matched: - @ConditionalOnClass found required class "com.yuqiyu.chapter28.HelloService"; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) - @ConditionalOnProperty (hello.enabled) matched (OnPropertyCondition) HelloAutoConfiguration#helloService matched: - @ConditionalOnMissingBean (types: com.yuqiyu.chapter28.HelloService; SearchStrategy: all) did not find any beans (OnBeanCondition) .....省略
在控制臺可以看到我們的自定義starter的自動化配置已經生效了,并且根據@ConditionalOnMissingBean(HelloService.class)做出了條件注入HelloService實體bean到SpringIoc容器內
編寫測試控制器我們來編寫一個簡單的測試控制器,查看HelloService在不配置參數情況下輸出格式化字符串內容,控制器代碼如下所示:
package com.yuqiyu.sample.testspringbootstarterhello; import com.yuqiyu.chapter28.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 測試自定義starter自動化配置HelloService * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/23 * Time:11:42 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @RestController public class HelloController { //注入自定義starter內邏輯 @Autowired HelloService helloService; /** * 測試訪問地址/hello * @return 格式化字符串 */ @RequestMapping(value = "/hello") public String sayHello() { return helloService.sayHello(); } }
接下來我們重啟下項目,訪問地址http://127.0.0.1:8080/hello,界面輸出內容如下所示:
Hello,HengYu
界面輸出的內容是我們默認值,接下來我們在application.properties配置文件內對應添加hello.msg、hello.show配置參數,如下所示:
#配置自定義starter參數 hello.msg=HengYu Boy hello.show=true
重啟項目,再次訪問地址,界面輸出內容如下所示:
Hello,HengYu Boy
我們的配置生效了,到目前為止我相信大家已經明白了我們application.properties配置文件為什么可以作為統一配置入口,為什么配置后可以被對應starter所使用。
總結以上內容是本章的全部講解,本章主要講解了我們如何自定義starter并且自動化配置到SpringBoot項目中,當然里面還有很多神奇的地方需要大家去深入挖掘。
本章代碼已經上傳到碼云:
網頁地址:http://git.oschina.net/jnyqy/lessons
Git地址:https://git.oschina.net/jnyqy/lessons.git
SpringBoot相關系列文章請訪問:目錄:SpringBoot學習目錄
QueryDSL相關系列文章請訪問:QueryDSL通用查詢框架學習目錄
感謝閱讀!
歡迎加入QQ技術交流群,共同進步。
QQ技術交流群
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67648.html
摘要:基于版本基于版本。由于中英行文差異,完全的逐字逐句翻譯會很冗余啰嗦。譯者在翻譯中同時參考了谷歌百度有道翻譯的譯文以及編程思想第四版中文版的部分內容對其翻譯死板,生造名詞,語言精煉度差問題進行規避和改正。 來源:LingCoder/OnJava8 主譯: LingCoder 參譯: LortSir 校對:nickChenyx E-mail: 本書原作者為 [美] Bru...
摘要:如何解決非集成情況下可能存在沖突的問題,有以下三種方案強制業務系統集成出現沖突時使用標明其自己已存在的沖突,以防止按注入出現的沖突異常。 我們開發內部用的二方庫時往往需要定義一些bean,這些bean中有的可能已經被業務方系統配置使用了,在非SpringBoot方式集成中可能導致沖突。導致按type注入失敗(因為存在兩個已有的實現)。為什么要強調非SpringBoot呢,因為Sprin...
摘要:還提供了全部參數的構造函數的自動生成,該注解的作用域也是只有在實體類上,因為只有實體類才會存在構造函數。當然除了全部參數的構造函數,還提供了沒有參數的構造函數,使用方式與一致。 Lombok對于Java偷懶開發者來說應該是比較中意的,恰恰筆者就是一個喜歡在小細節上偷懶來提高開發效率的人。所以在技術框架的海洋里尋找了很久才在GitHub開源平臺上找到,而在這之前國外很多程序猿一直使用該框...
摘要:創建工程涉及了,加上和的起步依賴。創建實體代碼清單如下創建頁面展示層啟動工程,訪問點擊參考資料源碼下載 這篇文件主要介紹通過springboot 去創建和提交一個表單。 創建工程 涉及了 web,加上spring-boot-starter-web和spring-boot-starter-thymeleaf的起步依賴。 org.springf...
閱讀 2612·2021-11-15 11:38
閱讀 2626·2021-11-04 16:13
閱讀 18061·2021-09-22 15:07
閱讀 1025·2019-08-30 15:55
閱讀 3270·2019-08-30 14:15
閱讀 1672·2019-08-29 13:59
閱讀 3226·2019-08-28 18:28
閱讀 1581·2019-08-23 18:29