throwable exception?SpringBoot是如何动起来的
- 软件开发
- 2023-08-13
- 90
各位老铁们好,相信很多人对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