springboot应用启动原理分析_第1页
springboot应用启动原理分析_第2页
springboot应用启动原理分析_第3页
springboot应用启动原理分析_第4页
springboot应用启动原理分析_第5页
已阅读5页,还剩13页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

springboot应用启动原理分析springboot应用启动原理分析/springboot应用启动原理分析springbootquickstart在springboot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个WebServer。如果之前没有使用过springboot可以通过下面的demo来感受下。

下面以这个工程为例,演示如何启动Springboot项目:gitclone:hengyunabc/spring—boot—demo。gitmvnspring-boot-demojava—jartarget/demo—0。0.1—SNAPSHOT.jar123如果使用的IDE是springsts或者idea,可以通过向导来创建springboot项目。也可以参考官方教程:

HYPERLINK”"\l”getting—started-first-application”\t”_blank"\l”getting—started—first—application"""\t"_blank”原始的Jar是这样子的:jar:0.0。1-SNAPSHOT。jar!/1jar包里的资源的URL:jar:0。0。1—SNAPSHOT.jar!/com/example/SpringBootDemoApplication.class1可以看到对于Jar里的资源,定义以’!/'来分隔.原始的Jar只支持一个’!/'。Springboot扩展了这个协议,让它支持多个’!/’,就可以表示jarinjar,jarindirectory的资源了。比如下面的URL表示demo—0.0。1—SNAPSHOT.jar这个jar里lib目录下面的spring-beans—4。2。3.RELEASE。jar里面的MANIFEST。MF:jar:0。0。1—SNAPSHOT.jar!/lib/spring—beans—4.2。3.RELEASE.jar!/META-INF/MANIFEST.MF1自定义URLStreamHandler,扩展Jar在构造一个URL时,可以传递一个Handler,而JDK自带有默认的Handler类,应用可以自己注册Handler来处理自定义的URL。publicURL(Stringprotocol,Stringhost,intport,Stringfile,URLStreamHandlerhandler)throwsMalformedURLException123456参考:

HYPERLINK”"\l”URL-java。lang。String—java.lang.String-int—java。lang.String—"\l”URL—java。lang.String—java.lang。String-int—java.lang。String—”\t”_blank"Springboot通过注册了一个自定义的Handler类来处理多重jarinjar的逻辑。这个Handler内部会用SoftReference来缓存所有打开过的JarFile。在处理像下面这样的URL时,会循环处理'!/’分隔符,从最上层出发,先构造出demo-0。0.1-SNAPSHOT。jar这个JarFile,再构造出spring-beans—4.2.3.RELEASE。jar这个JarFile,然后再构造出指向MANIFEST.MF的JarURLConnection。jar:0.0.1—SNAPSHOT。jar!/lib/spring—beans-4。2.3。RELEASE.jar!/META-INF/MANIFEST。MF1//org。springframework。boot.loader。jar。HandlerpublicclassHandlerextendsURLStreamHandler{privatestaticfinalStringSEPARATOR="!/";privatestaticSoftReference<Map〈File,JarFile>〉root;@OverrideprotectedURLConnectionopenConnection(URLurl)throwsIOException{if(this.jarnull){returnnewJarURLConnection(url,this.jarFile);}try{returnnewJarURLConnection(url,getRootJar(url));}catch(Exceptionex){returnopenFallbackConnection(url,ex);}}publicJar(URLurl)throwsIOException{Stringspec=url。getFile();intseparatorIndex=spec.indexOf(SEPARATOR);if(separatorIndex==—1){thrownewMalformedURLException("JarURLdoesnotcontain!/separator”);}Stringname=spec。substring(0,separatorIndex);returngetRootJar);}12345678910111213141516171819202122232425ClassLoader如何读取到Resource对于一个ClassLoader,它需要哪些能力?查找资源读取资源对应的API是:publicURLfindResource(Stringname)publicInputStreamgetResourceAsStream(Stringname)12上面提到,Springboot构造LaunchedURLClassLoader时,传递了一个URL[]数组。数组里是lib目录下面的jar的URL.对于一个URL,JDK或者ClassLoader如何知道怎么读取到里面的内容的?实际上流程是这样子的:LaunchedURLClassLoader。loadClassURL。getContent()URL.openConnection()Handler.openConnection(URL)最终调用的是JarURLConnection的getInputStream()函数。//org.springframework。boot。loader.jar.JarURLConnection@OverridepublicInputStreamgetInputStream()throwsIOException{connect();if(this.jarEntryName。isEmpty()){thrownewIOException("noentrynamespecified”);}returnthis。jarEntryData。getInputStream();}123456789从一个URL,到最终读取到URL里的内容,整个过程是比较复杂的,总结下:springboot注册了一个Handler来处理”jar:"这种协议的URLspringboot扩展了Jar,内部处理jarinjar的情况在处理多重jarinjar的URL时,springboot会循环处理,并缓存已经加载到的JarFile对于多重jarinjar,实际上是解压到了临时目录来处理,可以参考Jar里的代码在获取URL的InputStream时,最终获取到的是JarFile里的JarEntryData这里面的细节很多,只列出比较重要的一些点。然后,URLClassLoader是如何getResource的呢?URLClassLoader在构造时,有URL[]数组参数,它内部会用这个数组来构造一个URLClassPath:URLClassPathucp=newURLClassPath(urls);1在URLClassPath内部会为这些URLS都构造一个Loader,然后在getResource时,会从这些Loader里一个个去尝试获取.

如果获取成功的话,就像下面那样包装为一个Resource.ResourcegetResource(finalStringname,booleancheck){finalURLurl;try{url=newURL(base,ParseUtil.encodePath(name,false));}catch(MalformedURLExceptione){thrownewIllegalArgumentException("name”);}finalURLConnectionuc;try{if(check){URLClassPath。check(url);}uc=url.openConnection();InputStreamin=uc.getInputStream();if(ucinstanceofJarURLConnection){/*Needtorememberthejaritcanbeclosed*inahurry.*/JarURLConnectionjuc=(JarURLConnection)uc;jarfile=JarLoader.checkJar(juc.getJarFile());}}catch(Exceptione){returnnull;}returnnewResource(){publicStringgetName(){returnname;}publicURLgetURL(){returnurl;}publicURLgetCodeSourceURL(){returnbase;}publicInputStreamgetInputStream()throwsIOException{returnuc.getInputStream();}publicintgetContentLength()throwsIOException{returnuc.getContentLength();}};}123456789101112131415161718192021222324252627282930313233343536从代码里可以看到,实际上是调用了url.openConnection().这样完整的链条就可以连接起来了。注意,URLClassPath这个类的代码在JDK里没有自带,在这里看到

HYPERLINK””\l"506”\t"_blank”在IDE/开放目录启动Springboot应用在上面只提到在一个fatjar里启动Springboot应用的过程,下面分析IDE里Springboot是如何启动的.在IDE里,直接运行的Main函数是应用自己的Main函数:@SpringBootApplicationpublicclassSpringBootDemoApplication{publicstaticvoidmain(String[]args){SpringApplication。run(SpringBootDemoApplication.class,args);}}1234567其实在IDE里启动Springboot应用是最简单的一种情况,因为依赖的Jar都让IDE放到classpath里了,所以Springboot直接启动就完事了.还有一种情况是在一个开放目录下启动Springboot启动。所谓的开放目录就是把fatjar解压,然后直接启动应用。javaorg。springframework.boot。loader.JarLauncher1这时,Springboot会判断当前是否在一个目录里,如果是的,则构造一个ExplodedArchive(前面在jar里时是Jar),后面的启动流程类似fatjar的.EmbeadTomcat的启动流程判断是否在web环境springboot在启动时,先通过一个简单的查找Servlet类的方式来判断是不是在web环境:privatestaticfinalString[]WEB_ENVIRONMENT_CLASSES={"javax。servlet。Servlet",”org。springframework。web。context。ConfigurableWebApplicationContext”};privatebooleandeduceWebEnvironment(){for(StringclassName:WEB_ENVIRONMENT_CLASSES){if(!ClassUtils。isPresent(className,null)){returnfalse;}}returntrue;}1234567891011如果是的话,则会创建AnnotationConfigEmbeddedWebApplicationContext,否则Springcontext就是Ann

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论