摘要:代碼如下所示自定義業(yè)務(wù)實(shí)現(xiàn)恒宇少年碼云消息內(nèi)容是否顯示消息內(nèi)容,我們內(nèi)的代碼比較簡(jiǎn)單,根據(jù)屬性參數(shù)進(jìn)行返回格式化后的字符串。
在我們學(xué)習(xí)SpringBoot時(shí)都已經(jīng)了解到starter是SpringBoot的核心組成部分,SpringBoot為我們提供了盡可能完善的封裝,提供了一系列的自動(dòng)化配置的starter插件,我們?cè)谑褂?b>spring-boot-starter-web時(shí)只需要在pom.xml配置文件內(nèi)添加依賴就可以了,我們之前傳統(tǒng)方式則是需要添加很多相關(guān)SpringMVC配置文件。而spring-boot-starter-web為我們提供了幾乎所有的默認(rèn)配置,很好的降低了使用框架時(shí)的復(fù)雜度。
因此在使用xx.starter時(shí)你就不用考慮該怎么配置,即便是有一些必要的配置在application.properties配置文件內(nèi)對(duì)應(yīng)配置就可以了,那好,為什么我在application.properties配置對(duì)應(yīng)屬性后xx.starter就可以獲取到并作出處理呢?下面我們帶著這個(gè)疑問(wèn)來(lái)編寫我們自定義的starter讓我們深入了解SpringBoot
自定義starter并且通過(guò)spring-boot-autoconfigure完成自動(dòng)化配置。
構(gòu)建項(xiàng)目創(chuàng)建starter項(xiàng)目我們并不需要?jiǎng)?chuàng)建SpringBoot項(xiàng)目,我們創(chuàng)建一個(gè)Maven項(xiàng)目就可以滿足我們的需求,創(chuàng)建項(xiàng)目完成后pom.xml配置信息如下所示:
4.0.0 com.yuqiyu chapter28 1.0.0 jar UTF-8 org.springframework.boot spring-boot-autoconfigure 1.5.4.RELEASE
我們這個(gè)starter并不做其他復(fù)雜邏輯的編寫,所以這里的依賴只是添加了spring-boot-autoconfigure,實(shí)戰(zhàn)開(kāi)發(fā)時(shí)可以添加任意依賴到項(xiàng)目中。
配置映射參數(shù)實(shí)體我們?cè)谖恼麻_(kāi)頭埋下了一個(gè)疑問(wèn),starter是如何讀取application.properties或者application.yml配置文件內(nèi)需要的配置參數(shù)的呢?那么接下來(lái)我們就看看如何可以獲取自定義的配置信息。
SpringBoot在處理這種事情上早就已經(jīng)考慮到了,所以提供了一個(gè)注解@ConfigurationProperties,該注解可以完成將application.properties配置文件內(nèi)的有規(guī)則的配置參數(shù)映射到實(shí)體內(nèi)的field內(nèi),不過(guò)需要提供setter方法,自定義配置參數(shù)實(shí)體代碼如下所示:
package com.yuqiyu.chapter28; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 配置文件實(shí)體映射 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:51 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @ConfigurationProperties(prefix = "hello") public class HelloProperties { //消息內(nèi)容 private String msg = "HengYu"; //是否顯示消息內(nèi)容 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注解內(nèi)我們使用到了屬性preffix,該屬性配置了讀取參數(shù)的前綴,根據(jù)上面的實(shí)體屬性對(duì)應(yīng)配置文件內(nèi)的配置則是hello.msg、hello.show,當(dāng)然我們提供了默認(rèn)值,配置文件內(nèi)不進(jìn)行配置時(shí)則是使用默認(rèn)值。
編寫自定義業(yè)務(wù)我們?yōu)樽远xstarter提供一個(gè)Service,并且提供一個(gè)名為sayHello的方法用于返回我們配置的msg內(nèi)容。代碼如下所示:
package com.yuqiyu.chapter28; /** * 自定義業(yè)務(wù)實(shí)現(xiàn) * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:54 * 碼云:http://git.oschina.net/jnyqy * ======================== */ public class HelloService { //消息內(nèi)容 private String msg; //是否顯示消息內(nèi)容 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內(nèi)的代碼比較簡(jiǎn)單,根據(jù)屬性參數(shù)進(jìn)行返回格式化后的字符串。
接下來(lái)我們開(kāi)始編寫自動(dòng)配置,這一塊是starter的核心部分,配置該部分后在啟動(dòng)項(xiàng)目時(shí)才會(huì)自動(dòng)加載配置,當(dāng)然其中有很多細(xì)節(jié)性質(zhì)的配置
實(shí)現(xiàn)自動(dòng)化配置自動(dòng)化配置其實(shí)只是提供實(shí)體bean的驗(yàn)證以及初始化,我們先來(lái)看看代碼:
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自動(dòng)化配置 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/22 * Time:22:56 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @Configuration//開(kāi)啟配置 @EnableConfigurationProperties(HelloProperties.class)//開(kāi)啟使用映射實(shí)體對(duì)象 @ConditionalOnClass(HelloService.class)//存在HelloService時(shí)初始化該配置類 @ConditionalOnProperty//存在對(duì)應(yīng)配置信息時(shí)初始化該配置類 ( prefix = "hello",//存在配置前綴hello value = "enabled",//開(kāi)啟 matchIfMissing = true//缺失檢查 ) public class HelloAutoConfiguration { //application.properties配置文件映射前綴實(shí)體對(duì)象 @Autowired private HelloProperties helloProperties; /** * 根據(jù)條件判斷不存在HelloService時(shí)初始化新bean到SpringIoc * @return */ @Bean//創(chuàng)建HelloService實(shí)體bean @ConditionalOnMissingBean(HelloService.class)//缺失HelloService實(shí)體bean時(shí),初始化HelloService并添加到SpringIoc public HelloService helloService() { System.out.println(">>>The HelloService Not Found,Execute Create New Bean."); HelloService helloService = new HelloService(); helloService.setMsg(helloProperties.getMsg());//設(shè)置消息內(nèi)容 helloService.setShow(helloProperties.isShow());//設(shè)置是否顯示 return helloService; } }
自動(dòng)化配置代碼中有很多我們之前沒(méi)有用到的注解配置,我們從上開(kāi)始講解
@Configuration:這個(gè)配置就不用多做解釋了,我們一直在使用
@EnableConfigurationProperties:這是一個(gè)開(kāi)啟使用配置參數(shù)的注解,value值就是我們配置實(shí)體參數(shù)映射的ClassType,將配置實(shí)體作為配置來(lái)源。
有關(guān)@ConditionalOnXxx相關(guān)的注解這里要系統(tǒng)的說(shuō)下,因?yàn)檫@個(gè)是我們配置的關(guān)鍵,根據(jù)名稱我們可以理解為具有Xxx條件,當(dāng)然它實(shí)際的意義也是如此,條件注解是一個(gè)系列,下面我們?cè)敿?xì)做出解釋
@ConditionalOnBean:當(dāng)SpringIoc容器內(nèi)存在指定Bean的條件
@ConditionalOnClass:當(dāng)SpringIoc容器內(nèi)存在指定Class的條件
@ConditionalOnExpression:基于SpEL表達(dá)式作為判斷條件
@ConditionalOnJava:基于JVM版本作為判斷條件
@ConditionalOnJndi:在JNDI存在時(shí)查找指定的位置
@ConditionalOnMissingBean:當(dāng)SpringIoc容器內(nèi)不存在指定Bean的條件
@ConditionalOnMissingClass:當(dāng)SpringIoc容器內(nèi)不存在指定Class的條件
@ConditionalOnNotWebApplication:當(dāng)前項(xiàng)目不是Web項(xiàng)目的條件
@ConditionalOnProperty:指定的屬性是否有指定的值
@ConditionalOnResource:類路徑是否有指定的值
@ConditionalOnSingleCandidate:當(dāng)指定Bean在SpringIoc容器內(nèi)只有一個(gè),或者雖然有多個(gè)但是指定首選的Bean
@ConditionalOnWebApplication:當(dāng)前項(xiàng)目是Web項(xiàng)目的條件
以上注解都是元注解@Conditional演變而來(lái)的,根據(jù)不用的條件對(duì)應(yīng)創(chuàng)建以上的具體條件注解。
到目前為止我們還沒(méi)有完成自動(dòng)化配置starter,我們需要了解SpringBoot運(yùn)作原理后才可以完成后續(xù)編碼。
Starter自動(dòng)化運(yùn)作原理在注解@SpringBootApplication上存在一個(gè)開(kāi)啟自動(dòng)化配置的注解@EnableAutoConfiguration來(lái)完成自動(dòng)化配置,注解源碼如下所示:
// // 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注解內(nèi)使用到了@import注解來(lái)完成導(dǎo)入配置的功能,而EnableAutoConfigurationImportSelector內(nèi)部則是使用了SpringFactoriesLoader.loadFactoryNames方法進(jìn)行掃描具有META-INF/spring.factories文件的jar包。我們可以先來(lái)看下spring-boot-autoconfigure包內(nèi)的spring.factories文件內(nèi)容,如下所示:
# 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, .....省略
可以看到配置的結(jié)構(gòu)形式是Key=>Value形式,多個(gè)Value時(shí)使用,隔開(kāi),那我們?cè)谧远xstarter內(nèi)也可以使用這種形式來(lái)完成,我們的目的是為了完成自動(dòng)化配置,所以我們這里Key則是需要使用org.springframework.boot.autoconfigure.EnableAutoConfiguration
自定義spring.factories我們?cè)?b>src/main/resource目錄下創(chuàng)建META-INF目錄,并在目錄內(nèi)添加文件spring.factories,具體內(nèi)容如下所示:
#配置自定義Starter的自動(dòng)化配置 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yuqiyu.chapter28.HelloAutoConfiguration
都目前為止我們的自定義starter已經(jīng)配置完成,下面我們需要新建一個(gè)SpringBoot項(xiàng)目來(lái)測(cè)試我們的自動(dòng)化配置是否已經(jīng)生效。
創(chuàng)建測(cè)試SpringBoot項(xiàng)目在使用自定義starter之前需要將starter作Maven Jar Install到本地,我們使用idea工具自帶的maven命令完成該操作
步驟:工具右側(cè) -> Maven Projects -> Lifecycle -> install
創(chuàng)建測(cè)試項(xiàng)目的pom.xml配置文件內(nèi)容如下所示:
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配置文件內(nèi)
運(yùn)行測(cè)試在運(yùn)行項(xiàng)目之前,我們打開(kāi)application.properties配置文件開(kāi)啟debug模式,查看自動(dòng)化配置的輸出日志,配置內(nèi)容如下所示:
#顯示debug日志信息 debug=true
接下來(lái)我們啟動(dòng)項(xiàng)目,在控制臺(tái)查找是否存在我們的HelloAutoConfiguration日志輸出,控制臺(tái)輸出內(nèi)容如下所示:
.....省略 >>>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) .....省略
在控制臺(tái)可以看到我們的自定義starter的自動(dòng)化配置已經(jīng)生效了,并且根據(jù)@ConditionalOnMissingBean(HelloService.class)做出了條件注入HelloService實(shí)體bean到SpringIoc容器內(nèi)
編寫測(cè)試控制器我們來(lái)編寫一個(gè)簡(jiǎn)單的測(cè)試控制器,查看HelloService在不配置參數(shù)情況下輸出格式化字符串內(nèi)容,控制器代碼如下所示:
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; /** * 測(cè)試自定義starter自動(dòng)化配置HelloService * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/7/23 * Time:11:42 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @RestController public class HelloController { //注入自定義starter內(nèi)邏輯 @Autowired HelloService helloService; /** * 測(cè)試訪問(wèn)地址/hello * @return 格式化字符串 */ @RequestMapping(value = "/hello") public String sayHello() { return helloService.sayHello(); } }
接下來(lái)我們重啟下項(xiàng)目,訪問(wèn)地址http://127.0.0.1:8080/hello,界面輸出內(nèi)容如下所示:
Hello,HengYu
界面輸出的內(nèi)容是我們默認(rèn)值,接下來(lái)我們?cè)?b>application.properties配置文件內(nèi)對(duì)應(yīng)添加hello.msg、hello.show配置參數(shù),如下所示:
#配置自定義starter參數(shù) hello.msg=HengYu Boy hello.show=true
重啟項(xiàng)目,再次訪問(wèn)地址,界面輸出內(nèi)容如下所示:
Hello,HengYu Boy
我們的配置生效了,到目前為止我相信大家已經(jīng)明白了我們application.properties配置文件為什么可以作為統(tǒng)一配置入口,為什么配置后可以被對(duì)應(yīng)starter所使用。
總結(jié)以上內(nèi)容是本章的全部講解,本章主要講解了我們?nèi)绾巫远xstarter并且自動(dòng)化配置到SpringBoot項(xiàng)目中,當(dāng)然里面還有很多神奇的地方需要大家去深入挖掘。
本章代碼已經(jīng)上傳到碼云:
網(wǎng)頁(yè)地址:http://git.oschina.net/jnyqy/lessons
Git地址:https://git.oschina.net/jnyqy/lessons.git
SpringBoot相關(guān)系列文章請(qǐng)?jiān)L問(wèn):目錄:SpringBoot學(xué)習(xí)目錄
QueryDSL相關(guān)系列文章請(qǐng)?jiān)L問(wèn):QueryDSL通用查詢框架學(xué)習(xí)目錄
感謝閱讀!
歡迎加入QQ技術(shù)交流群,共同進(jìn)步。
QQ技術(shù)交流群
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67648.html
摘要:基于版本基于版本。由于中英行文差異,完全的逐字逐句翻譯會(huì)很冗余啰嗦。譯者在翻譯中同時(shí)參考了谷歌百度有道翻譯的譯文以及編程思想第四版中文版的部分內(nèi)容對(duì)其翻譯死板,生造名詞,語(yǔ)言精煉度差問(wèn)題進(jìn)行規(guī)避和改正。 來(lái)源:LingCoder/OnJava8 主譯: LingCoder 參譯: LortSir 校對(duì):nickChenyx E-mail: 本書原作者為 [美] Bru...
摘要:如何解決非集成情況下可能存在沖突的問(wèn)題,有以下三種方案強(qiáng)制業(yè)務(wù)系統(tǒng)集成出現(xiàn)沖突時(shí)使用標(biāo)明其自己已存在的沖突,以防止按注入出現(xiàn)的沖突異常。 我們開(kāi)發(fā)內(nèi)部用的二方庫(kù)時(shí)往往需要定義一些bean,這些bean中有的可能已經(jīng)被業(yè)務(wù)方系統(tǒng)配置使用了,在非SpringBoot方式集成中可能導(dǎo)致沖突。導(dǎo)致按type注入失敗(因?yàn)榇嬖趦蓚€(gè)已有的實(shí)現(xiàn))。為什么要強(qiáng)調(diào)非SpringBoot呢,因?yàn)镾prin...
摘要:還提供了全部參數(shù)的構(gòu)造函數(shù)的自動(dòng)生成,該注解的作用域也是只有在實(shí)體類上,因?yàn)橹挥袑?shí)體類才會(huì)存在構(gòu)造函數(shù)。當(dāng)然除了全部參數(shù)的構(gòu)造函數(shù),還提供了沒(méi)有參數(shù)的構(gòu)造函數(shù),使用方式與一致。 Lombok對(duì)于Java偷懶開(kāi)發(fā)者來(lái)說(shuō)應(yīng)該是比較中意的,恰恰筆者就是一個(gè)喜歡在小細(xì)節(jié)上偷懶來(lái)提高開(kāi)發(fā)效率的人。所以在技術(shù)框架的海洋里尋找了很久才在GitHub開(kāi)源平臺(tái)上找到,而在這之前國(guó)外很多程序猿一直使用該框...
摘要:創(chuàng)建工程涉及了,加上和的起步依賴。創(chuàng)建實(shí)體代碼清單如下創(chuàng)建頁(yè)面展示層啟動(dòng)工程,訪問(wèn)點(diǎn)擊參考資料源碼下載 這篇文件主要介紹通過(guò)springboot 去創(chuàng)建和提交一個(gè)表單。 創(chuàng)建工程 涉及了 web,加上spring-boot-starter-web和spring-boot-starter-thymeleaf的起步依賴。 org.springf...
閱讀 2600·2021-11-15 11:38
閱讀 2618·2021-11-04 16:13
閱讀 17981·2021-09-22 15:07
閱讀 1014·2019-08-30 15:55
閱讀 3261·2019-08-30 14:15
閱讀 1663·2019-08-29 13:59
閱讀 3207·2019-08-28 18:28
閱讀 1575·2019-08-23 18:29