throwable exception?SpringBoot是如何動起來的

各位老鐵們好,相信很多人對throwable exception都不是特別的了解,因此呢,今天就來為大家分享下關于throwable exception以及Spring...
各位老鐵們好,相信很多人對throwable exception都不是特別的了解,因此呢,今天就來為大家分享下關于throwable exception以及SpringBoot是如何動起來的的問題知識,還望可以幫助大家,解決大家的一些困惑,下面一起來看看吧!
java web項目中如何優雅的處理異常
如果Java方法不能按照正常的流程執行,那么可以通過另外一種途徑退出:拋出一個封裝了錯誤信息的對象,這個就是Java的異常;當發生異常時,后面的代碼無法繼續執行,而是由異常處理器繼續執行。
01.異常的分類Throwable是所有異常的超類,下一級可以分為Error和Exception:
1.Error
Error是指Java運行時系統內部的錯誤,或者說它代表了JVM本身的錯誤,通常都是比較嚴重的錯誤,比如內存溢出,虛擬機錯誤等等;
Error通常和硬件或JVM有關,和程序本身無關,所以不能被代碼捕獲和處理。
2.Exception
我們經常說的異常是指Exception,又可以分成運行時異常和檢查異常。
RuntimeException:運行時異常,這類異常在編譯期間不強制代碼捕捉,但是可能在在JVM運行期間拋出異常;出現此類異常,通常是代碼的問題,所以需要修改程序避免這類異常。常見的運行時異常,比如:NullPointerException、ClassCastException等等。
CheckedException:檢查異常,這種異常發生在編譯階段,Java編譯器會強制代碼去捕獲和處理此類異常;比如:ClassNotFoundException、IllegalAccessException等等。
02.異常的處理方法捕獲異常使用try...catch語句,把可能發生異常的代碼放到try{...}中,然后使用catch捕獲對應的異常;
我們也可以在代碼塊中使用Throw向上級代碼拋出異常;
在方法中使用throws關鍵字,向上級代碼拋出異常;
03.Throw和throws的區別Throw在方法內,后面跟著異常對象;而throws是用在方法上,后面跟異常類;
Throw會拋出具體的異常對象,當執行到Throw的時候,方法內的代碼也就執行結束了;throws用來聲明異常,提醒調用方這個方法可能會出現這種異常,請做好處理的準備,但是不一定會真的出現異常。
04.如何優雅地處理異常不要試圖通過異常來控制程序流程,比如開發一個接口,正確的做法是對入參進行非空驗證,當參數為空的時候返回“參數不允許為空”,而不應該捕捉到空指針的時候返回錯誤提示。
僅捕獲有必要的代碼,盡量不要用一個try...catch包住大段甚至整個方法內所有的代碼,因為這樣會影響JVM對代碼進行優化,從而帶來額外的性能開銷。
很多程序員喜歡catch(Exceptione),其實應該盡可能地精確地指出是什么異常。
不要忽略異常,捕捉到異常之后千萬不能什么也不做,要么在catch{...}中輸出異常信息,要么通過Throw或throws拋出異常,讓上層代碼處理。
盡量不要在catch{...}中輸出異常后,又向上層代碼拋出異常,因為這樣會輸出多條異常信息,而且它們還是相同的,這樣可能會產生誤導。
不要在finally{...}中寫return,因為try{...}在執行return之前執行finally{...},如果finally{...}中有return,那么將不再執行try{...}中的return。
我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。SpringBoot是如何動起來的
程序入口
SpringApplication.run(BeautyApplication.class,args);
執行此方法來加載整個SpringBoot的環境。
1.從哪兒開始?
SpringApplication.java
/**
*RuntheSpringapplication,creatingandrefreshinganew
*{@linkApplicationContext}.
*@paramargstheapplicationarguments(usuallypassedfromaJavamainmethod)
*@returnarunning{@linkApplicationContext}
*/
publicConfigurableApplicationContextrun(String...args){
//...
}
調用SpringApplication.java中的run方法,目的是加載SpringApplication,同時返回ApplicationContext。
2.執行了什么?
2.1計時
記錄整個SpringApplication的加載時間!
StopWatchstopWatch=newStopWatch();
stopWatch.start();
//...
stopWatch.stop();
if(this.logStartupInfo){
newStartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(),stopWatch);
}
2.2聲明
指定java.awt.headless,默認是true一般是在程序開始激活headless模式,告訴程序,現在你要工作在Headlessmode下,就不要指望硬件幫忙了,你得自力更生,依靠系統的計算能力模擬出這些特性來。
privatevoidconfigureHeadlessProperty(){
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,System.getProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,Boolean.toString(this.headless)));
}
2.4配置監聽并發布應用啟動事件
SpringApplicationRunListener負責加載ApplicationListener事件。
SpringApplicationRunListenerslisteners=getRunListeners(args);
//開始
listeners.starting();
//處理所有propertysources配置和profiles配置,準備環境,分為標準Servlet環境和標準環境
ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,applicationArguments);
//準備應用上下文
prepareContext(context,environment,listeners,applicationArguments,printedBanner);
//完成
listeners.started(context);
//異常
handleRunFailure(context,ex,exceptionReporters,listeners);
//執行
listeners.running(context);
getRunListeners中根據type=SpringApplicationRunListener.class去拿到了所有的Listener并根據優先級排序。
對應的就是META-INF/spring.factories文件中的org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener
private<T>Collection<T>getSpringFactoriesInstances(Class<T>type,
Class<?>[]parameterTypes,Object...args){
ClassLoaderclassLoader=Thread.currentThread().getContextClassLoader();
//Usenamesandensureuniquetoprotectagainstduplicates
Set<String>names=newLinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type,classLoader));
List<T>instances=createSpringFactoriesInstances(type,parameterTypes,
classLoader,args,names);
AnnotationAwareOrderComparator.sort(instances);
returninstances;
}
復制代碼
在ApplicationListener中,可以針對任何一個階段插入處理代碼。
publicinterfaceSpringApplicationRunListener{
/**
*Calledimmediatelywhentherunmethodhasfirststarted.Canbeusedforvery
*earlyinitialization.
*/
voidstarting();
/**
*Calledoncetheenvironmenthasbeenprepared,butbeforethe
*{@linkApplicationContext}hasbeencreated.
*@paramenvironmenttheenvironment
*/
voidenvironmentPrepared(ConfigurableEnvironmentenvironment);
/**
*Calledoncethe{@linkApplicationContext}hasbeencreatedandprepared,but
*beforesourceshavebeenloaded.
*@paramcontexttheapplicationcontext
*/
voidcontextPrepared(ConfigurableApplicationContextcontext);
/**
*Calledoncetheapplicationcontexthasbeenloadedbutbeforeithasbeen
*refreshed.
*@paramcontexttheapplicationcontext
*/
voidcontextLoaded(ConfigurableApplicationContextcontext);
/**
*Thecontexthasbeenrefreshedandtheapplicationhasstartedbut
*{@linkCommandLineRunnerCommandLineRunners}and{@linkApplicationRunner
*ApplicationRunners}havenotbeencalled.
*@paramcontexttheapplicationcontext.
*@since2.0.0
*/
voidstarted(ConfigurableApplicationContextcontext);
/**
*Calledimmediatelybeforetherunmethodfinishes,whentheapplicationcontexthas
*beenrefreshedandall{@linkCommandLineRunnerCommandLineRunners}and
*{@linkApplicationRunnerApplicationRunners}havebeencalled.
*@paramcontexttheapplicationcontext.
*@since2.0.0
*/
voidrunning(ConfigurableApplicationContextcontext);
/**
*Calledwhenafailureoccurswhenrunningtheapplication.
*@paramcontexttheapplicationcontextor{@codenull}ifafailureoccurredbefore
*thecontextwascreated
*@paramexceptionthefailure
*@since2.0.0
*/
voidfailed(ConfigurableApplicationContextcontext,Throwableexception);
}
3.每個階段執行的內容
3.1listeners.starting();
在加載SpringApplication之前執行,所有資源和環境未被加載。
3.2prepareEnvironment(listeners,applicationArguments);
創建ConfigurableEnvironment;將配置的環境綁定到SpringApplication中;
privateConfigurableEnvironmentprepareEnvironment(
SpringApplicationRunListenerslisteners,
ApplicationArgumentsapplicationArguments){
//Createandconfiguretheenvironment
ConfigurableEnvironmentenvironment=getOrCreateEnvironment();
configureEnvironment(environment,applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if(this.webApplicationType==WebApplicationType.NONE){
environment=newEnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
ConfigurationPropertySources.attach(environment);
returnenvironment;
}
3.3prepareContext
配置忽略的Bean;
privatevoidconfigureIgnoreBeanInfo(ConfigurableEnvironmentenvironment){
if(System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME)==null){
Booleanignore=environment.getProperty("spring.beaninfo.ignore",
Boolean.class,Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
}
打印日志-加載的資源
BannerprintedBanner=printBanner(environment);
根據不同的WebApplicationType創建Context
context=createApplicationContext();
3.4refreshContext
支持定制刷新
/**
*RegisterashutdownhookwiththeJVMruntime,closingthiscontext
*onJVMshutdownunlessithasalreadybeenclosedatthattime.
*<p>Thismethodcanbecalledmultipletimes.Onlyoneshutdownhook
*(atmax)willberegisteredforeachcontextinstance.
*@seejava.lang.Runtime#addShutdownHook
*@see#close()
*/
voidregisterShutdownHook();
3.5afterRefresh
刷新后的實現方法暫未實現
/**
*Calledafterthecontexthasbeenrefreshed.
*@paramcontexttheapplicationcontext
*@paramargstheapplicationarguments
*/
protectedvoidafterRefresh(ConfigurableApplicationContextcontext,
ApplicationArgumentsargs){
}
3.6listeners.started(context);
到此為止,SpringApplication的環境和資源都加載完畢了;發布應用上下文啟動完成事件;執行所有Runner運行器-執行所有ApplicationRunner和CommandLineRunner這兩種運行器
//啟動
callRunners(context,applicationArguments);
3.7listeners.running(context);
觸發所有SpringApplicationRunListener監聽器的running事件方法
希望對你有幫助
好了,關于throwable exception和SpringBoot是如何動起來的的問題到這里結束啦,希望可以解決您的問題哈!
本文鏈接:http://xinin56.com/ruanjian/3329.html