您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring Application怎么配置”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Application怎么配置”吧!
目前Spring Boot已經(jīng)發(fā)展到2.3.4.RELEASE ,對于它的好處網(wǎng)上也是鋪天蓋地的,這里就不再重復(fù)了。直接說重點,從Spring Boot1.x一步步跟著迭代升級到現(xiàn)在的2.3.4也是遇到了很多的坑,了解其新版本的特性是非常重要的,可以幫助我們避免很多不必要的麻煩。
因為我也一直在搞基于Spring Boot技術(shù)棧的組件開發(fā)工作,最近準(zhǔn)備針對基礎(chǔ)組件進(jìn)行部分重構(gòu),所以順便把當(dāng)前版本的特性從頭在順一遍,就當(dāng)是回顧總結(jié)了,這個回顧只介紹目前版本的一些特性,不對特性展開來敘述,如果有興趣可以@我,后面我也會根據(jù)某一塊來進(jìn)行詳細(xì)的分析。喜歡的朋友可以跟著看一看,希望對你有所幫助。
如果應(yīng)用啟動失敗,Spring Boot會幫我們把大概為什么會啟動失敗的信息打印在日志中,如下面我用6080端口第二次啟動應(yīng)用就會提示我如下
*************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container failed to start. Port 6080 was already in use. Action: Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
有了這種友好的提示真是幸福感爆棚啊,而且Spring Boot 還給我們提供了更多的擴(kuò)展接口FailureAnalyzer,并提供了響應(yīng)得抽象類AbstractFailureAnalyzer。如果我們不滿足他默認(rèn)的啟動異常信息,就可以通過FailureAnalyzer 來進(jìn)行一些定制化開發(fā)(比如在異常發(fā)生的時候打印堆棧等).FailureAnalyzer的擴(kuò)展使用了SPI的方式,所以在我們使用的時候需要在應(yīng)用內(nèi)創(chuàng)建META-INF/spring.factories,來聲明下我們的實現(xiàn),下面上個小demo。
/** 首先創(chuàng)建我們自己的類,并且可以根據(jù)自己的需要來進(jìn)行異常攔截,這里我攔截的就是端口占用異常PortInUseException * @ClassName LearningFailureAnalyzer * @Author QIANGLU * @Date 2020/9/23 9:10 下午 * @Version 1.0 */ public class LearningFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { private static final Logger LOGGER = LoggerFactory.getLogger(LearningFailureAnalyzer.class); @Override protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) { LOGGER.error("我出異常了,哇卡卡卡卡卡卡"); return new FailureAnalysis("端口:" +cause.getPort()+"被占用",cause.getMessage(),rootFailure); } } //第二步就是創(chuàng)建個META-INF/spring.factories 了,如下 org.springframework.boot.diagnostics.FailureAnalyzer=\ com.qianglu.chapter1.failure.LearningFailureAnalyzer //第三布啟動兩次我們的應(yīng)用,就會發(fā)現(xiàn),打印的信息是我們需要的了 *************************** APPLICATION FAILED TO START *************************** Description: 端口:6080被占用 Action: Port 6080 is already in use
這東西可用場景其實很多很多,大家想一想有沒有點啟發(fā)
在Spring Boot剛出的時候,因為啟動加載慢還被人吐槽過,這不,現(xiàn)在懶加載來了。允許你的應(yīng)用開啟懶加載,你的beans 不需要在項目啟動的時候被創(chuàng)建了,啥時候用啥時候在創(chuàng)建。這樣就能節(jié)省你很多啟動時間,但有利就有弊,懶加載這玩意在web應(yīng)用中會導(dǎo)致你很多web相關(guān)的bean也被延遲加載,知道有請求進(jìn)來才會被初始化,所以在使用的時候一定要注意,否則就會有叫你很懵逼的異常了。
并且官方也說了,你都延遲初始化了,那有些問題可能也會延遲被發(fā)現(xiàn)。比如我們以前某些配置配錯了,經(jīng)常會在啟動的時候就報XXXbean不能被找到之類的。嘿嘿,現(xiàn)在可就不了,一樣的啟動成功,只有在你用的時候給你掉鏈子,就問你怕不怕吧。
還有就是官方提示延遲初始化的,會導(dǎo)致初期jvm 內(nèi)存表現(xiàn)比較小,但要注意配置足夠的內(nèi)存給未來對象創(chuàng)建使用(我覺得一般應(yīng)用這都不是問題,不需要過多關(guān)注)。
下面我們就來看看兩種配置方式:
使用SpringApplication調(diào)用setLazyInitialization 方法設(shè)置
使用配置spring.main.lazy-initialization=true
如果你設(shè)置了延遲初始化,又有某些特殊的類想初始化,那可以配置@Lazy(false) 關(guān)閉其懶加載。
這玩意說實話我一直不知道有啥用,以前我們都是配置個大佛保平安,娛樂性大于實際吧,當(dāng)然也許有沒GET到的點。
配置方式也很簡單,就是在你的classpath下放個banner.txt,通過spring.banner.location 配置來指定下文件位置。當(dāng)然還有很多屬性,什么編碼、gif、version之類的我其實懶得說了,沒啥興趣。
####4、配置你的SpringApplication
咱們一般啟動類都是直接調(diào)用SpringApplication.run就行了。但如果你覺得太簡單沒啥意思,那其實SpringApplication.run 里面有很多有意思的屬性你可以去看看,比如我關(guān)閉banner
public static void main(String[] args) { SpringApplication app = new SpringApplication(MySpringConfiguration.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); }
當(dāng)然還有很多配置屬性,你也可以使用application.yml來配置SpringApplication 的屬性。
官方提供了SpringApplicationBuilder 類來幫大家使用流式構(gòu)建的方式來創(chuàng)建多級的ApplicationContext。SpringApplicationBuilder可以幫助我們構(gòu)建一種層級關(guān)系,如下這種方式等于SpringApplication.run
new SpringApplicationBuilder() .sources(Parent.class) .child(Application.class) .bannerMode(Banner.Mode.OFF) .run(args);
這里說的其實就是k8s的Liveness 和 Readiness ,他們已經(jīng)成為了Spring Boot的核心。
簡單說下,Liveness 和 Readiness 在k8s中代表了應(yīng)用程序狀態(tài)的各個方面。
Liveness 狀態(tài)來查看內(nèi)部情況可以理解為health check,如果Liveness失敗就就意味著應(yīng)用處于故障狀態(tài)并且目前無法恢復(fù),這種情況就重啟吧。
Readiness 狀態(tài)用來告訴應(yīng)用是否已經(jīng)準(zhǔn)備好接受客戶端請求,如果Readiness未就緒那么k8s就不能路由流量過來。
我們可以用代碼來監(jiān)聽Readiness狀態(tài),并進(jìn)行我們需要的處理
@Component public class ReadinessStateExporter { @EventListener public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) { switch (event.getState()) { case ACCEPTING_TRAFFIC: // xxxxx break; case REFUSING_TRAFFIC: // xxxxxx break; } } }
我們也能在應(yīng)用出現(xiàn)故障不能被恢復(fù)的時候改變此狀態(tài)來進(jìn)行動態(tài)的降級和隔離,這個真是太爽了,有機(jī)會建議大家試一試
@Component public class LocalCacheVerifier { private final ApplicationEventPublisher eventPublisher; public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void checkLocalCache() { try { //... } catch (CacheCompletelyBrokenException ex) { AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN); } } }
Spring Boot的事件通知機(jī)制,簡直是解耦神器,包括Spring Cloud的用的分布式遠(yuǎn)程通知機(jī)制其實核心也是這個,這是增加了一層中間件來進(jìn)行消息的傳遞。
有些事件因為實在ApplicationContext創(chuàng)建前就觸發(fā)了,所以很多時候不能使用@Bean來聲明這些事件。最好使用SpringApplication.addListeners(…)
和 SpringApplicationBuilder.listeners(…)
來注冊監(jiān)聽器。
但如果你真是把握不了這些加載時機(jī)的話,那有個萬能的辦法就是配置SPI擴(kuò)展,直接在META-INF/spring.factories 配置,加上你得listener就行了,如:org.springframework.context.ApplicationListener=com.example.project.MyListener
官方介紹了寫在啟動時候會發(fā)送的事件順序:
1、ApplicationStartingEvent 在運行開始的時候發(fā)送事件
2、ApplicationEnvironmentPreparedEvent 當(dāng)Environment在上下文中被使用的時候發(fā)送事件
3、ApplicationContextInitializedEvent 在所有的bean定義前,ApplicationContext準(zhǔn)備好并且ApplicationContextInitializers已經(jīng)被調(diào)用的時候發(fā)送事件
4、ApplicationPreparedEvent 刷新配置前、bean的定義加載之后發(fā)送事件
5、ApplicationStartedEvent 刷新上下文后,在執(zhí)行CommandLineRunner的實現(xiàn)之前
6、AvailabilityChangeEvent 發(fā)送LivenessState.CORRECT 表面應(yīng)用是活躍狀態(tài)
7、ApplicationReadyEvent 在執(zhí)行CommandLineRunner接口之后發(fā)送
8、AvailabilityChangeEvent 發(fā)送ReadinessState.ACCEPTING_TRAFFIC 后代表應(yīng)用可以接入流量
9、ApplicationFailedEvent 發(fā)送應(yīng)用啟動失敗事件
上面的只是SpringApplicationEvent
的事件,一般咱們也不需要對這些進(jìn)行操作,帶你得知道它的存在,以免出了問題都不知道怎么找,其實人家Spring Boot已經(jīng)都發(fā)給你了。
一般使用SpringApplication就會為我們正確的創(chuàng)建ApplicationContext類型,用于確定WebApplicationType 也就是應(yīng)用類型的方式其實很簡單:
如果存在Spring MVC 就使用AnnotationConfigServletWebServerApplicationContext
如果Spring MVC不存 在,但是Spring WebFlux存在,就使用AnnotationConfigReactiveWebServerApplicationContext
都沒有的話就用AnnotationConfigApplicationContext
如果你既用了Spring MVC 又用了Spring WebFlux WebClient,Spring MVC 這一套是默認(rèn)使用的,除非你設(shè)置SpringApplication.setWebApplicationType(WebApplicationType)來強(qiáng)制改變。
如果你想訪問SpringApplication.run(…) 的參數(shù),你其實可以注入一個org.springframework.boot.ApplicationArguments 對象,ApplicationArguments這個接口提供對原始String[] 參數(shù)以及已解析的選項和非選項參數(shù)的訪問,上demo:
import org.springframework.boot.*; import org.springframework.beans.factory.annotation.*; import org.springframework.stereotype.*; @Component public class MyBean { @Autowired public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"] } }
Spring Boot 中的環(huán)境變量也注冊了一個CommandLinePropertySource,我們可以使用@Value來獲取某個環(huán)境變量。
這倆貨也是我們經(jīng)常會用到的東西,如果你需要在項目啟動時加載一些東西,那它倆簡直就是神器了,這倆接口都提供了一個run方法,這個方法會在SpringApplication.run(…) 執(zhí)行完成前被調(diào)用。這倆接口適合哪種在應(yīng)用接收請求前來處理一些東西。
舉個使用例子
import org.springframework.boot.*; import org.springframework.stereotype.*; @Component public class MyBean implements CommandLineRunner { public void run(String... args) { // Do something... } }
如果咱們定義了多個CommandLineRunner或ApplicationRunner實現(xiàn),有的時候又需要有個先后順序來執(zhí)行,那就可以用org.springframework.core.annotation.Order 這個注解來定義下。
每個SpringApplication 都會像JVM注冊一個關(guān)閉鉤子(shutdown hook ),來確保能夠正常的退出。保證@PreDestroy 注解和DisposableBean 接口這些回調(diào)都被執(zhí)行。
另外,如果你想在使用SpringApplication.exit() 時返回一些特殊的退出代碼,可以實現(xiàn)org.springframework.boot.ExitCodeGenerator接口,傳遞給System.exit() 進(jìn)行返回。如:
@SpringBootApplication public class ExitCodeApplication { @Bean public ExitCodeGenerator exitCodeGenerator() { return () -> 42; } public static void main(String[] args) { System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args))); } }
ExitCodeGenerator接口可以通過異常實現(xiàn)。遇到此類異常時,Spring Boot返回實現(xiàn)的getExitCode() 方法提供的退出代碼
我們可以使用spring.application.admin.enabled 屬性來開啟管理員功能。開了的話就會把你自己的SpringApplicationAdminMXBean
全部暴露給MBeanServer咯,當(dāng)然你也可以用這種特性來遠(yuǎn)程操作你應(yīng)用。但你要想明白其中的安全性問題,沒啥必要的話還是不要亂搞。
感謝各位的閱讀,以上就是“Spring Application怎么配置”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring Application怎么配置這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。