1.springԴ?源码?????????
2.springboot如何启动内置tomcat?(源码详解)
3.springå¯å¨åç(springå·¥ç¨å¯å¨)
4.一文看懂SpringBoot的启动原理
5.SpringBoot启动过程详解
6.springmvc启动过程?
springԴ??????????
深入理解Spring启动原理,对于架构师而言至关重要。启动SpringBoot项目常见流量入口包括Rpc、过程Http和MQ。源码如果在错误时机开启流量,启动如在Spring初始化过程中,过程gdb查看源码文件可能导致业务代码中的源码事件订阅组件未启动,从而引发线上故障。启动正确做法是过程确保项目在Spring启动完成后开启入口流量。理解Spring启动顺序与扩展点,源码能够帮助解决这一问题。启动
Spring的过程启动流程包含多个关键扩展点,例如BeanFactoryPostProcessor、源码实例化Bean、启动Autowired装配依赖、过程BeanNameAware、BeanFactoryAware、ApplicationContextAware等。了解这些扩展点的执行顺序,有助于深入理解Spring启动机制。
在Spring启动过程中,首先执行BeanFactoryPostProcessor接口,允许修改Bean定义和属性值。接着实例化Bean,然后通过Autowired装配依赖,注意此时被依赖的Bean可能还未初始化。之后执行BeanNameAware、BeanFactoryAware和ApplicationContextAware的set方法,设置Bean的名称、工厂和上下文。接下来,执行BeanPostProcessor的postProcessBeforeInitialization方法,允许自定义逻辑处理。PostConstruct方法随后执行,紧接着InitializingBean和afterPropertiesSet方法,最后执行init-method方法。所有单例Bean初始化完成后,执行SmartInitializingSingleton接口方法,此时适合开启入口流量。
理解Spring启动顺序与扩展点,不仅有助于解决线上故障,手机直播源码延迟还能在开发过程中做出明智决策。例如,Http、MQ和Rpc入口流量应在SmartInitializingSingleton之后开启,避免在错误时机开启流量,导致Spring Event机制未初始化完成而引发问题。
Spring提供多个扩展点,如发布ContextRefreshedEvent事件,注册和初始化Spring MVC,以及监听端口等。掌握这些知识,能够帮助架构师更好地管理应用启动过程,确保系统稳定运行。了解Spring初始化的关键代码,有助于深入理解Spring内部工作原理。最后,Spring Boot外部的CommandLineRunner在Spring上下文启动完成后才执行,说明Spring完全启动后才会开启Http流量。
总结,SpringBoot在系统完全启动后才开启流量,建议在SmartLifecyle或ContextRefreshedEvent等位置注册服务,开启流量。例如,Spring Cloud Eureka服务发现组件就是在SmartLifecype中注册服务的。深入理解这些原理,对于提升系统性能和稳定性至关重要。
springboot如何启动内置tomcat?(源码详解)
SpringBoot项目启动时,无需依赖传统Tomcat,因为内部集成了Tomcat功能。本文将深入解析SpringBoot如何通过源码启动内置Tomcat。
关键点在于`registerBeanPostProcessors`的`onRefresh`方法,它扩展了容器对象和bean实例化过程,确保单例和实例化完成。`initApplicationEventMuliticaster`则注册广播对象,与`applicationEvent`和`applicationListener`紧密相关。
文章的核心内容集中在`onRefresh()`方法,其中`createWenServer()`是关键。当`servletContext`和`webServer`为空时,会创建并初始化相关的组件,如`servletWebServerFactory`、saas源码小程序`servletContext`(Web请求上下文)、`webServer`(抽象的web容器封装)和`WebServer`实例。`getWebServer()`方法允许在Spring容器刷新后连接webServer。
SpringBoot通过`TomcatServletWebServerFactory`获取webServer,该工厂负责创建和配置webServer,包括Tomcat组件的初始化,如`Connector`和`Context`的设置,以及与wrapper、engine、service和host等的关联。`new Connector`会根据传入的协议进行定制化配置。
理解了这些扩展点,用户可以自定义配置,通过`ServerProperties`或自定义`tomcatConnectorCustomizers`和`tomcatProtocolHandlerCustomizers`来扩展Tomcat的连接器和协议处理器。这就是SpringBoot设计的巧妙之处。
最后,SpringBoot的启动流程涉及逐层初始化和启动Tomcat的组件,如engine、context和wrapper,它们通过生命周期方法如`init`、`start`和`destroy`协同工作。启动过程本质上是一个链式调用,每个组件的初始化和启动都会触发下一层组件的逻辑。
springå¯å¨åç(springå·¥ç¨å¯å¨)
SpringBootå¯å¨åçåæ
èªå¨é ç½®æ ¸å¿ç±»SpringFactoriesLoader
ä¸é¢å¨è¯´@EnableAutoConfigurationçæ¶åæ说META-INFä¸çspring.factoriesæ件ï¼é£ä¹è¿ä¸ªæ件æ¯æä¹è¢«springå è½½å°çå¢ï¼å ¶å®å°±æ¯SpringFactoriesLoaderç±»ã
SpringFactoriesLoaderæ¯ä¸ä¸ªä¾Springå é¨ä½¿ç¨çéç¨å·¥åè£ è½½å¨å®éï¼SpringFactoriesLoaderéæ两个æ¹æ³ï¼
å¨è¿ä¸ªSpringBootåºç¨å¯å¨è¿ç¨ä¸ï¼SpringFactoriesLoaderåäºä»¥ä¸å 件äºï¼
å è½½ææMETA-INF/spring.factoriesä¸çInitializer
å è½½ææMETA-INF/spring.factoriesä¸çListener
å è½½EnvironmentPostProcessorï¼å 许å¨Springåºç¨æ建ä¹åå®å¶ç¯å¢é ç½®ï¼
æ¥ä¸æ¥å è½½PropertiesåYAMLçPropertySourceLoaderï¼é对SpringBootç两ç§é ç½®æ件çå è½½å¨ï¼
åç§å¼å¸¸æ åµçFailureAnalyzerï¼å¼å¸¸è§£éå¨ï¼
å è½½SpringBootå é¨å®ç°çåç§AutoConfiguration
模æ¿å¼æTemplateAvailabilityProviderï¼å¦FreemarkerãThymeleafãJspãVelocityçï¼
æ»å¾æ¥è¯´ï¼SpringFactoriesLoaderå@EnableAutoConfigurationé åèµ·æ¥ï¼æ´ä½åè½å°±æ¯æ¥æ¾spring.factoriesæ件ï¼å è½½èªå¨é 置类ã
æ´ä½å¯å¨æµç¨
å¨æ们æ§è¡å ¥å£ç±»çmainæ¹æ³ä¹åï¼è¿è¡SpringApplication.runï¼åé¢newäºä¸ä¸ªSpringApplication对象ï¼ç¶åæ§è¡å®çrunæ¹æ³ã
åå§åSpringApplicationç±»
å建ä¸ä¸ªSpringApplication对象æ¶ï¼ä¼è°ç¨å®èªå·±çinitializeæ¹æ³
æ§è¡æ ¸å¿runæ¹æ³
åå§åinitializeæ¹æ³æ§è¡å®ä¹åï¼ä¼è°ç¨runæ¹æ³ï¼å¼å§å¯å¨SpringBootã
é¦å éåæ§è¡ææéè¿SpringFactoriesLoaderï¼å¨å½åclasspathä¸çMETA-INF/spring.factoriesä¸æ¥æ¾ææå¯ç¨çSpringApplicationRunListeners并å®ä¾åãè°ç¨å®ä»¬çstarting()æ¹æ³ï¼æ¶²è½éç¥è¿äºçå¬å¨SpringBootåºç¨å¯å¨ã
å建并é ç½®å½åSpringBootåºç¨å°è¦ä½¿ç¨çEnvironmentï¼å æ¬å½åææçPropertySource以åProfileã
éåè°ç¨ææçSpringApplicationRunListenersçenvironmentPrepared()çæ¹æ³ï¼éç¥è¿äºçå¬å¨SpringBootåºç¨çEnvironmentå·²ç»å®æåå§åã
æå°SpringBootåºç¨çbannerï¼SpringApplicationçshowBannerå±æ§ä¸ºtrueæ¶ï¼å¦æclasspathä¸åå¨banner.txtæ件ï¼åæå°å ¶å 容ï¼å¦åæå°é»è®¤bannerã
æ ¹æ®å¯å¨æ¶è®¾ç½®çapplicationContextClassåå¨initializeæ¹æ³è®¾ç½®çwebEnvironmentï¼å建对åºçapplicationContextã
å建å¼å¸¸è§£æå¨ï¼ç¨å¨å¯å¨ä¸åçå¼å¸¸çæ¶åè¿è¡å¼å¸¸å¤ç(å æ¬è®°å½æ¥å¿ãéæ¾èµæºç)ã
设置SpringBootçEnvironmentï¼æ³¨åSpringBeanå称çåºååå¨BeanNameGeneratorï¼å¹¶è®¾ç½®èµæºå è½½å¨ResourceLoaderï¼éè¿SpringFactoriesLoaderå è½½ApplicationContextInitializeråå§åå¨ï¼è°ç¨initializeæ¹æ³ï¼å¯¹å建çApplicationContextè¿ä¸æ¥åå§åã
è°ç¨ææçSpringApplicationRunListenersçcontextPreparedæ¹æ³ï¼éç¥é¹ç»å·è¿äºListenerå½åApplicationContextå·²ç»å建å®æ¯ã
ææ ¸å¿çä¸æ¥ï¼å°ä¹åéè¿@EnableAutoConfigurationè·åçææé 置以åå ¶ä»å½¢å¼çIoC容å¨é ç½®å è½½å°å·²ç»åå¤å®æ¯çApplicationContextã
è°ç¨ææçSpringApplicationRunListenerçcontextLoadedæ¹æ³ï¼å è½½åå¤å®æ¯çApplicationContextã
è°ç¨refreshContextï¼æ³¨åä¸ä¸ªå ³éSpring容å¨çé©åShutdownHookï¼å½ç¨åºå¨åæ¢çæ¶åéæ¾èµæºï¼å æ¬ï¼éæ¯Beanï¼å ³éSpringBeançå建工åçï¼
注ï¼é©åå¯ä»¥å¨ä»¥ä¸å ç§åºæ¯ä¸è¢«è°ç¨ï¼
1ï¼ç¨åºæ£å¸¸éåº
2ï¼ä½¿ç¨System.exit()
3ï¼ç»ç«¯ä½¿ç¨Ctrl+C触åçä¸æ
4ï¼ç³»ç»å ³é
5ï¼ä½¿ç¨Killpidå½ä»¤ææ»è¿ç¨
è·åå½åææApplicationRunneråCommandLineRunneræ¥å£çå®ç°ç±»ï¼æ§è¡å ¶runæ¹æ³
éåææçSpringApplicationRunListenerçfinished()æ¹æ³ï¼å®æSpringBootçå¯å¨ã
springå·¥ä½åç
Springçå·¥ä½åçæ¯è®©ä¸ä¸ªå¯¹è±¡çå建ä¸ç¨newå°±å¯ä»¥èªå¨çç产ï¼å¨è¿è¡æ¶ä¸xmlSpringçé ç½®æ件æ¥é«å²©å¨æçå建对象åè°ç¨å¯¹è±¡ï¼èä¸éè¦éè¿ä»£ç æ¥å ³èã
Springæ¯ä¸ä¸ªå¼æ¾æºä»£ç ç设计å±é¢æ¡æ¶ï¼ä»è§£å³çæ¯ä¸å¡é»è¾å±åå ¶ä»åå±çæ¾è¦åé®é¢ï¼å æ¤å®å°é¢åæ¥å£çç¼ç¨ææ³è´¯ç©¿æ´ä¸ªç³»ç»åºç¨ã
springç¹ç¹æ¯1.æ¹ä¾¿è§£è¦ï¼ç®åå¼åã2.AOPç¼ç¨çæ¯æã3.声æå¼äºå¡çæ¯æã4.æ¹ä¾¿ç¨åºçæµè¯ã5.æ¹ä¾¿éæåç§ä¼ç§æ¡æ¶ã6.éä½JavaEEAPIç使ç¨é¾åº¦ã7.Javaæºç æ¯ç»å ¸å¦ä¹ èä¾ã
Springæ¡æ¶æ¯ç±äºè½¯ä»¶å¼åçå¤ææ§èå建çãSpring使ç¨çæ¯åºæ¬çJavaBeanæ¥å®æ以ååªå¯è½ç±EJBå®æçäºæ ãç¶èï¼Springçç¨éä¸ä» ä» éäºæå¡å¨ç«¯çå¼åãä»ç®åæ§ãå¯æµè¯æ§åæ¾è¦åæ§è§åº¦èè¨ï¼ç»å¤§é¨åJavaåºç¨é½å¯ä»¥ä»Springä¸å¸¦æ¶åçãSpringæ¯ä¸ä¸ªè½»é级çæ§å¶å转(IoC)åé¢ååé¢(AOP)ç容å¨æ¡æ¶ã
Springéè¿ä¸ç§ç§°ä½æ§å¶å转ï¼IoCï¼çææ¯ä¿è¿äºæ¾è¦åãå½åºç¨äºIoCï¼ä¸ä¸ªå¯¹è±¡ä¾èµçå ¶å®å¯¹è±¡ä¼éè¿è¢«å¨çæ¹å¼ä¼ éè¿æ¥ï¼èä¸æ¯è¿ä¸ªå¯¹è±¡èªå·±å建æè æ¥æ¾ä¾èµå¯¹è±¡ãä½ å¯ä»¥è®¤ä¸ºIoCä¸JNDIç¸åââä¸æ¯å¯¹è±¡ä»å®¹å¨ä¸æ¥æ¾ä¾èµï¼èæ¯å®¹å¨å¨å¯¹è±¡åæè¡å¾¡å§åæ¶ä¸ç对象请æ±å°±ä¸»å¨å°ä¾èµä¼ éç»å®ã
springçåçæ¯ä»ä¹ï¼ä¸ãIoC(Inversionofcontrol):æ§å¶å转\x0d\1ãIoCï¼\x0d\æ¦å¿µï¼æ§å¶æç±å¯¹è±¡æ¬èº«è½¬å容å¨ï¼ç±å®¹å¨æ ¹æ®é ç½®è ¢è¡«æ件å»å建å®ä¾å¹¶å建å个å®ä¾ä¹é´çä¾èµå ³ç³»\x0d\æ ¸å¿ï¼beanå·¥åï¼å¨Springä¸ï¼beanå·¥åå建çå个å®ä¾ç§°ä½bean\x0d\äºãAOP(Aspect-OrientedProgramming):é¢åæ¹é¢ç¼ç¨ã\x0d\1ã代çç两ç§æ¹å¼ï¼\x0d\éæ代çï¼\x0d\é对æ¯ä¸ªå ·ä½ç±»åå«ç¼å代çç±»ã\x0d\é对ä¸ä¸ªæ¥å£ç¼åä¸ä¸ªä»£çç±»ã\x0d\å¨æ代çï¼\x0d\é对ä¸ä¸ªæ¹é¢ç¼åä¸ä¸ªInvocationHandlerï¼ç¶ååç¨JDKåå°å ä¸çProxy类为åç§æ¥å£å¨æçæç¸åºç代çç±»ã\x0d\2ãAOPç主è¦åçï¼å¨æ代çã\x0d\Springå·¥ä½åç\x0d\Springå·²ç»ç¨è¿ä¸æ®µæ¶é´äºï¼æè§Springæ¯ä¸ªå¾ä¸éçæ¡æ¶ãå é¨ææ ¸å¿çå°±æ¯IOCäºï¼\x0d\å¨ææ³¨å ¥ï¼è®©ä¸ä¸ªå¯¹è±¡çå建ä¸ç¨newäºï¼å¯ä»¥èªå¨çç产ï¼è¿å ¶å®å°±æ¯å©ç¨javaéçåå°ï¼åå°å ¶å®å°±æ¯å¨è¿è¡æ¶å¨æçå»å建ãè°ç¨å¯¹è±¡ï¼Springå°±æ¯å¨è¿è¡æ¶ï¼è·xmlSpringçé ç½®æ件æ¥å¨æçå建对象ï¼åè°ç¨å¯¹è±¡éçæ¹æ³çã\x0d\Springè¿æä¸ä¸ªæ ¸å¿å°±æ¯AOPè¿ä¸ªå°±æ¯é¢ååé¢ç¼ç¨ï¼å¯ä»¥ä¸ºæä¸ç±»å¯¹è±¡è¿è¡çç£åæ§å¶ï¼ä¹å°±æ¯å¨è°ç¨è¿ç±»å¯¹è±¡çå ·ä½æ¹æ³çååå»è°ç¨ä½ æå®ç模åï¼ä»èè¾¾å°å¯¹ä¸ä¸ªæ¨¡åæ©å çåè½ãè¿äºé½æ¯éè¿é 置类达å°è°åºçã\x0d\Springç®çå«æ¡£æ¡ï¼å°±æ¯è®©å¯¹è±¡ä¸å¯¹è±¡ï¼æ¨¡åä¸æ¨¡åï¼ä¹é´çå ³ç³»æ²¡æéè¿ä»£ç æ¥å ³èï¼é½æ¯éè¿é 置类说æ管ççï¼Springæ ¹æ®è¿äºé ç½®å é¨éè¿åå°å»å¨æçç»è£ 对象ï¼\x0d\è¦è®°ä½ï¼Springæ¯ä¸ä¸ªå®¹å¨ï¼å¡æ¯å¨å®¹å¨éç对象æä¼æSpringææä¾çè¿äºæå¡ååè½ã\x0d\Springéç¨çæç»å ¸çä¸ä¸ªè®¾è®¡æ¨¡å¼å°±æ¯ï¼æ¨¡æ¿æ¹æ³æ¨¡å¼ã
SpringBootåºç¨å¯å¨åç(äº)æ©å±URLClassLoaderå®ç°åµå¥jarå è½½å¨ä¸ç¯æç« ãSpringBootåºç¨å¯å¨åç(ä¸)å°å¯å¨èæ¬åµå ¥jarãä¸ä»ç»äºSpringBootå¦ä½å°å¯å¨èæ¬ä¸RunnableJaræ´å为ExecutableJarçåçï¼ä½¿å¾çæçjar/waræ件å¯ä»¥ç´æ¥å¯å¨
æ¬ç¯å°ä»ç»SpringBootå¦ä½æ©å±URLClassLoaderå®ç°åµå¥jarçç±»(èµæº)å è½½ï¼ä»¥å¯å¨æ们çåºåæ£æç¨ã
é¦å 岩ä¼ï¼ä»ä¸ä¸ªç®åç示ä¾å¼å§
build.gradle
WebApp.java
æ§è¡gradlebuildæ建jarå ï¼éé¢å å«åºç¨ç¨åºã第ä¸æ¹ä¾èµä»¥åSpringBootå¯å¨ç¨åºï¼å ¶ç®å½ç»æå¦ä¸
æ¥çMANIFEST.MFçå 容(MANIFEST.MFæ件çä½ç¨è¯·èªè¡GOOGLE)
å¯ä»¥çå°ï¼jarçå¯å¨ç±»ä¸ºorg.springframework.boot.loader.JarLauncherï¼è并ä¸æ¯æ们çcom.manerfan.SpringBoot.theory.WebAppï¼åºç¨ç¨åºå ¥å£ç±»è¢«æ 记为äºStart-Class
jarå¯å¨å¹¶ä¸æ¯éè¿åºç¨ç¨åºå ¥å£ç±»ï¼èæ¯éè¿JarLauncher代çå¯å¨ãå ¶å®SpringBootæ¥æ3ä¸ä¸åçLauncherï¼JarLauncherãWarLauncherãPropertiesLauncher
SpringBoot使ç¨Launcher代çå¯å¨ï¼å ¶æéè¦çä¸ç¹ä¾¿æ¯å¯ä»¥èªå®ä¹ClassLoaderï¼ä»¥å®ç°å¯¹jaræ件å ï¼jarinjarï¼æå ¶ä»è·¯å¾ä¸jarãclassæèµæºæ件çå è½½
å ³äºClassLoaderçæ´å¤ä»ç»å¯åèãæ·±å ¥ç解JVMä¹ClassLoaderã
SpringBootæ½è±¡äºArchiveçæ¦å¿µï¼ä¸ä¸ªArchiveå¯ä»¥æ¯jarï¼JarFileArchiveï¼ï¼å¯ä»¥æ¯ä¸ä¸ªæ件ç®å½ï¼ExplodedArchiveï¼ï¼å¯ä»¥æ½è±¡ä¸ºç»ä¸è®¿é®èµæºçé»è¾å±ã
ä¸ä¾ä¸ï¼spring-boot-theory-1.0.0.jaræ¢ä¸ºä¸ä¸ªJarFileArchiveï¼spring-boot-theory-1.0.0.jar!/BOOT-INF/libä¸çæ¯ä¸ä¸ªjarå ä¹æ¯ä¸ä¸ªJarFileArchive
å°spring-boot-theory-1.0.0.jar解åå°ç®å½spring-boot-theory-1.0.0ï¼åç®å½spring-boot-theory-1.0.0为ä¸ä¸ªExplodedArchive
æç §å®ä¹ï¼JarLauncherå¯ä»¥å è½½å é¨/BOOT-INF/libä¸çjarå/BOOT-INF/classesä¸çåºç¨class
å ¶å®JarLauncherå®ç°å¾ç®å
å ¶ä¸»å ¥å£æ°å»ºäºJarLauncher并è°ç¨ç¶ç±»Launcherä¸çlaunchæ¹æ³å¯å¨ç¨åº
åå建JarLauncheræ¶ï¼ç¶ç±»ExecutableArchiveLauncheræ¾å°èªå·±æå¨çjarï¼å¹¶å建archive
å¨Launcherçlaunchæ¹æ³ä¸ï¼éè¿ä»¥ä¸archiveçgetNestedArchivesæ¹æ³æ¾å°/BOOT-INF/libä¸ææjarå/BOOT-INF/classesç®å½æ对åºçarchiveï¼éè¿è¿äºarchivesçurlçæLaunchedURLClassLoaderï¼å¹¶å°å ¶è®¾ç½®ä¸ºçº¿ç¨å¥½æ©¡ä¸ä¸æç±»å è½½å¨ï¼å¯å¨åºç¨
è³æ¤ï¼ææ§è¡æ们åºç¨ç¨åºä¸»å ¥å£ç±»çmainæ¹æ³ï¼ææåºç¨ç¨åºç±»æ件åå¯éè¿/BOOT-INF/classeså è½½ï¼ææä¾èµç第ä¸æ¹jaråå¯éè¿/BOOT-INF/libå è½½
å¨åæLaunchedURLClassLoaderåï¼é¦å äºè§£ä¸ä¸URLStreamHandler
javaä¸å®ä¹äºURLçæ¦å¿µï¼å¹¶å®ç°å¤ç§URLåè®®ï¼è§URLï¼*http**file**ftp**jar*çï¼ç»å对åºçURLConnectionå¯ä»¥çµæ´»å°è·ååç§åè®®ä¸çèµæº
对äºjarï¼æ¯ä¸ªjaré½ä¼å¯¹åºä¸ä¸ªurlï¼å¦
jar:file:/data/spring-boot-theory/BOOT-INF/lib/spring-aop-5.0.4.RELEASE.jar!/
jarä¸çèµæºï¼ä¹ä¼å¯¹åºä¸ä¸ªurlï¼å¹¶ä»¥'!/'åå²ï¼å¦
jar:file:/data/spring-boot-theory/BOOT-INF/lib/spring-aop-5.0.4.RELEASE.jar!/org/springframework/aop/SpringProxy.class
对äºåå§çJarFileURLï¼åªæ¯æä¸ä¸ª'!/'ï¼SpringBootæ©å±äºæ¤åè®®ï¼ä½¿å ¶æ¯æå¤ä¸ª'!/'ï¼ä»¥å®ç°jarinjarçèµæºï¼å¦
jar:file:/data/spring-boot-theory.jar!/BOOT-INF/lib/spring-aop-5.0.4.RELEASE.jar!/org/springframework/aop/SpringProxy.class
èªå®ä¹URLçç±»æ ¼å¼ä¸º[pkgs].[protocol].Handlerï¼å¨è¿è¡Launcherçlaunchæ¹æ³æ¶è°ç¨äºJarFile.registerUrlProtocolHandler()以注åèªå®ä¹çHandler
å¨å¤çå¦ä¸URLæ¶ï¼ä¼å¾ªç¯å¤ç'!/'åé符ï¼ä»æä¸å±åºåï¼å æé spring-boot-theory.jarçJarFileï¼åæé spring-aop-5.0.4.RELEASE.jarçJarFileï¼æåæé æåSpringProxy.classç
JarURLConnectionï¼éè¿JarURLConnectionçgetInputStreamæ¹æ³è·åSpringProxy.classå 容
ä»ä¸ä¸ªURLï¼å°è¯»åå ¶ä¸çå 容ï¼æ´ä¸ªè¿ç¨ä¸º
URLClassLoaderå¯ä»¥éè¿åå§çjaråè®®ï¼å è½½jarä¸ä»classæ件
LaunchedURLClassLoaderéè¿æ©å±çjaråè®®ï¼ä»¥å®ç°jarinjarè¿ç§æ åµä¸çclassæ件å è½½
æ建warå å¾ç®å
æ建åºçwarå ï¼å ¶ç®å½æºæ为
MANIFEST.MFå 容为
æ¤æ¶ï¼å¯å¨ç±»å为äºorg.springframework.boot.loader.WarLauncherï¼æ¥çWarLauncherå®ç°ï¼å ¶å®ä¸JarLauncher并æ 太大差å«
å·®å«ä» å¨äºï¼JarLauncherå¨æ建LauncherURLClassLoaderæ¶ï¼ä¼æç´¢BOOT-INF/classesç®å½åBOOT-INF/libç®å½ä¸jarï¼WarLauncherå¨æ建LauncherURLClassLoaderæ¶ï¼åä¼æç´¢WEB-INFO/classesç®å½åWEB-INFO/libåWEB-INFO/lib-provided两个ç®å½ä¸çjar
å¦æ¤ä¾èµï¼æ建åºçwar便æ¯æ两ç§å¯å¨æ¹å¼
PropretiesLauncherçå®ç°ä¸JarLauncherWarLauncherçå®ç°æ为ç¸ä¼¼ï¼éè¿PropretiesLauncherå¯ä»¥å®ç°æ´ä¸ºè½»éçthinjarï¼å ¶å®ç°æ¹å¼å¯èªè¡æ¥é æºç
SpringBootè¿è¡åçSpringBootæ¯ä¸ä¸ªåºäºSpringå¼åï¼éæäºå¤§é第ä¸æ¹åºé ç½®çjavawebå¼åæ¡æ¶
pom.xml
ç¶ä¾èµ
å ¶ä¸å®ä¸»è¦æ¯ä¾èµä¸ä¸ªç¶é¡¹ç®ï¼ä¸»è¦æ¯ç®¡ç项ç®çèµæºè¿æ»¤åæ件ã以åæä»¬å¯¼å ¥ä¾èµé»è®¤æ¯ä¸éè¦åçæ¬çã
å¯å¨å¨spring-boot-starter
springboot-boot-starter-xxx:spring-bootçåºæ¯å¯å¨å¨é御
spring-boot-starter-web:帮æä»¬å¯¼å ¥äºweb模åæ£å¸¸è¿è¡æä¾èµçç»ä»¶ã
springBootå°ææçåè½åºæ¯é½æ½ååºæ¥ï¼åæä¸ä¸ªä¸ªçstarter(å¯å¨å¨)ï¼åªéè¦å¨é¡¹ç®ä¸å¼å ¥è¿äºstarterå³å¯ï¼ææç¸å ³çä¾èµé½ä¼è¢«å¼è¿æ¥ï¼æ们è¦ç¨ä»ä¹åè½å°±å¯¼å ¥ä»ä¹æ ·çåºæ¯å¯å¨å¨å³å¯ã
@SpringBootApplication
ä½ç¨ï¼æ 注å¨æ个类ä¸è¯´æè¿ä¸ªç±»æ¯SpringBootç主é 置类ï¼SpringBootè¿è¡è¿ä¸ªç±»çmainæ¹æ³æ¥å¯å¨SpringBootåºç¨ã
è¿å ¥è¿ä¸ªæ³¨è§£ï¼éé¢å å«äºå¾å¤å ¶ä»æ³¨è§£
@ComponentScanä½ç¨ï¼èªå¨æ«æ并å 载符åæ¡ä»¶çç»ä»¶æè beanï¼å°è¿ä¸ªbeanå®ä¹å è½½å°IOC容å¨ä¸ã
@SpringBootConfigurationä½ç¨ï¼SpringBootçé 置类ï¼æ 注å¨æ个类ä¸ï¼è¡¨ç¤ºè¿æ¯ä¸ä¸ªå§¿åSpringBootçé 置类ã
è¿å ¥@SpringBootConfiguration注解æ¥çï¼è¿éç@Configuration说æè¿æ¯ä¸ä¸ªé 置类ï¼é 置类对åºSpringçxmlé ç½®æ件ã
继ç»æ¥ç@SpringBootConfigurationå å«çå ¶ä»æ³¨è§£
@EnableAutoConfigurationï¼å¼å¯èªå¨é ç½®åè½
è¿å ¥@EnableAutoConfiguration注解æ¥ç
@AutoConfigurationPackageèªå¨é ç½®å
@importï¼Springåºå±æ³¨è§£@importï¼ç»å®¹å¨ä¸å¯¼å ¥ä¸ä¸ªç»ä»¶
@Importï¼{ AutoConfigurationImportSelector.class}ï¼ç»å®¹å¨å¯¼å ¥ç»ä»¶
AutoConfigurationImportSelectorï¼èªå¨é ç½®å¯¼å ¥éæ©å¨ãé£ä¹å®å¯¼å ¥åªäºç»ä»¶çéæ©å¨å¢
è¿ä¸ªç±»ä¸æè¿æ ·ä¸ä¸ªæ¹æ³ï¼getCandidateConfiguration,èå¨è¿ä¸ªæ¹æ³ä¸æè°ç¨äºSpringFactoriesLoaderç±»çéææ¹æ³loadFactoryNames()æ¹æ³
è¿å ¥loadSpringFactoriesæ¹æ³
æ ¹æ®å ¨å±æç´¢Spring.factoriesï¼æå¼åæ¯èªå¨é ç½®çæ件ã
é便æå¼ä¸ä¸ªå ¶ä¸çèªå¨é 置类çï¼å®ä»¬é½åå岩æ¯javaConfigé 置类ï¼é½æ³¨å ¥äºä¸äºBean
æ以ï¼èªå¨é ç½®çæ£å®ç°æ¯ä»classpathä¸æ寻ææçMETA-INF/spring.factoriesé ç½®æ件ï¼å¹¶å°å ¶ä¸å¯¹åºçorg.springframework.boot.autoconfigureå ä¸çé 置项éè¿åå°å®ä¾å为对åºæ 注äº@ConfigurationçjavaConfigå½¢å¼çIOC容å¨é 置类ï¼ç¶åå°è¿äºé½æ±æ»æ为ä¸ä¸ªå®ä¾å¹¶å è½½å°IOC容å¨ä¸ã
ç»è®ºï¼
1.SpringBootå¨å¯å¨çæ¶åä»ç±»è·¯å¾ä¸çMETA-INF/spring.factoriesä¸è·åEnableAutoConfigurationæå®çå¼
2.å°è¿äºå¼ä½ä¸ºèªå¨é ç½®ç±»å¯¼å ¥å®¹å¨ï¼èªå¨é 置类就çæï¼å¸®æ们è¿è¡èªå¨é 置工ä½ã
3.æ´ä¸ªJ2EEçæ´ä½è§£å³æ¹æ¡åèªå¨é ç½®é½å¨springboot-autoConfigureçjarå ä¸ã
4.å®ä¼ç»å®¹å¨ä¸å¯¼å ¥é常å¤çèªå¨é 置类ï¼xxxAutoConfigurationï¼,å°±æ¯ç»å®¹å¨ä¸å¯¼å ¥è¿ä¸ªåºæ¯éè¦çææç»ä»¶ï¼å¹¶é 置好è¿äºç»ä»¶ã
5.æäºèªå¨é 置类ï¼å å»äºæ们æå¨ç¼åé ç½®æ³¨å ¥åè½ç»ä»¶ççå·¥ä½ã
SpringApplication
è¿ä¸ªç±»ä¸»è¦åäºä»¥ä¸å件äº
1.æ¨æåºç¨çç±»åæ¯æ®éç项ç®è¿æ¯web项ç®
2.æ¥æ¾å¹¶å è½½ææå¯ç¨åå§åå¨ï¼è®¾ç½®å°initializerså±æ§ä¸
3.æ¾åºææçåºç¨ç¨åºçå¬å¨ï¼è®¾ç½®å°listenerså±æ§ä¸
4.æ¨æ并设置mainæ¹æ³çå®ä¹ç±»ï¼æ¾å°è¿è¡ç主类
SpringbootBatchçå¯å¨åç-ConfigurationSpringbootæ´åäºwebåbatchï¼ä½æ¯ä»ä»¬è¯å®ä¸æ¯åä¸æ¡è·¯ï¼å¨springbootä¸ï¼ä¼æ¨æå½åçè¿è¡ç¯å¢ãthis.webApplicationType=WebApplicationType.deduceFromClasspath();
ä»ä¸ç¨¿æ¨±æå¯ä»¥çåºï¼Springå°è¯ä»classpathéæ¾å°ç¹å¾ç±»ï¼æ¥å¤æå½åappæ¯ä»ä¹ç±»åãå½ç¶è¿ç§å¤ææ¯æå±éæ§çï¼æå¯è½æ¯transitive带ææ¸è¿æ¥ä¸ä¸ªå¸¦æservletç类被å½æäºWebApplicationType.SERVLETï¼å®é ä¸æ¯ä¸ªWebApplicationType.NONE;ãå¦æä¸æ³ä»¥webè¿è¡å°±æ¯æ³è¿è¡batchå¯ä»¥å¨application.properties强è¡æå®WebApplicationType
å ·ä½åçä½ç¨ç请çä¸é¢çstacktrace
å½ä¸ä¸ªbatchapplicationéè¦å¯å¨ï¼éè¦é ç½®JobRepositoryï¼Datasourceççï¼ææçå¼å§é½æ¥èªä¸ä¸ªannotation@EnableBatchProcessing
å½å å ¥@EnableBatchProcessingæ¶ï¼BatchConfigurationSelectorå¼å§å¯å¨ï¼æä¹å¯å¨ç大家å¯ä»¥é®æä¸åèä¸é¢çstacktraceã
import类主è¦æ¯ç±ConfigurationClassPostProcessoræ¥å®ç°çãå½BatchConfigurationSelector被è°ç¨çæ¶åï¼æ们å¯ä»¥çå°ä»æ两æ¡æ¯è·¯ã
é£ä¹è¿ä¸¤æ¡è·¯æå¥ä¸åå¢ã主è¦æ¯jobå®ä¹çæ¹å¼ä¸åã
modular=trueçæ åµä¸ï¼ä¸é¢æ¯ä¸ä¸ªä¾å
å¯ä»¥æå¤ä¸ªåAp
一文看懂SpringBoot的启动原理
探究SpringBoot启动原理,深入理解其打包与启动过程。
SpringBoot在打包时形成一个可运行的"FatJar"结构,JDKClassLoader仅能识别该Jar中的class文件与classpath下的其他jar包中的class文件,无法加载嵌入的jar包。
Java中URLStreamHandler类负责根据不同协议打开链接,JDK内置多个协议处理器如jar、file、http。URL内部静态HashTable保存已发现协议与处理器映射。
SpringBoot定义了描述资源的接口Archive,实现类包括在文件夹与jar包中查找资源。在fatJar中使用后者。
SpringBoot使用插件进行打包,生成包含MANIFEST.MF文件的结构,程序启动类为SpringBoot的JarLauncher。
启动方法由JarLauncher继承自ExecutableArchiveLauncher实现,webrtc源码拉取构建当前main方法所在fatJar的JarFileArchive对象。通过JarLauncher#main方法启动程序,关键在于SpringBoot自定义classLoader识别fatJar资源。
为了实现目标,SpringBoot定制了读取多个!/的URL路径,构建自定义ClassLoaderLaunchedURLClassLoader,该类继承自UrlClassLoader,通过传入的Url数组加载class文件,使用自定义Handler获取资源。
至此,SpringBoot自定义ClassLoader成功加载fatJar中的依赖包class文件。通过SpringBoot提供思路,可实现读取fatJar内部资源并加载class文件,性能上优于频繁文件解压。
SpringBoot内部实现复杂,自行解析Zip文件,但其实现核心在于读取fatJar内部资源。JDK的JarFile功能同样可实现此目标。自定义ClassLoader加载二进制数据定义Class对象是常见项目实现。
SpringBoot定制的Zip解析器在类加载阶段避免频繁解压,性能提升明显。理解SpringBoot启动原理,深入其打包与启动机制,对于构建高效、灵活的微服务架构至关重要。
SpringBoot启动过程详解
尽管SpringBoot以其简洁的外观吸引人,但其内部机制实则复杂且功能强大。它凭借自动配置功能,根据应用程序的类路径和依赖关系,自动配置了必要的组件,如引入数据库依赖时,会自动配置数据库连接池和数据源。 SpringBoot默认采用Tomcat作为内嵌的Servlet容器,通过启动类SpringApplication简化了启动过程,包括自动配置和组件扫描等步骤,以实现快速启动。 尽管不深入探讨内部细节,但本文将主要聚焦在SpringBoot的启动流程上。SpringApplication的核心作用在于启动过程中的四个关键步骤:识别应用程序类型,区分普通项目和Web项目
加载并设置所有可用的cpp源码实战系列初始化器,存入initializers属性
寻找并配置所有应用程序监听器,存入listeners属性
推断并设置主方法定义的类,确定运行的主入口
SpringBoot的启动流程大致可以总结为上述四个步骤。这就是SpringBoot启动过程的简单概述。springmvc启动过程?
SpringMVC流程是什么
springmvc工作流程如下。客户端发送请求;核心控制器DispatcherServlet接收到请求,通过系统或映射器配置找到对应的handler,并将控制器controller返回给核心控制器。
spring工作的流程流程如下:用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求可以访问Servlet、哪些不能访问。就是url-pattern的作用,并且会加载springmvc.xml配置文件。
SpringWebMVC处理Http请求的大致过程:\x0d\一旦Http请求到来,DispatcherSevlet将负责将请求分发。DispatcherServlet可以认为是Spring提供的前端控制器,所有的请求都有经过它来统一分发。
springmvc的工作原理,简单的概括一下DispatcherServlet将请求提交到Controller。Controller调用业务逻辑处理后,返回ModelAndView。DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。视图负责将结果显示到客户端。
springmvc是基于servlet实现的。运行速度:因为过滤器底层是servlet,所以springmvc的运行速度会稍微比structs2快。struts2是多例的springmvc单例的参数封装:struts2参数封装是基于属性进行封装。springmvc是基于方法封装。
请求的第一站到达的是Spring的DispatcherServlet,它是一个前端控制器,工作是将用户的请求委托给其他的组件(这里是交给SpringMVC的控制器)去处理。
m代表model模型,v代表view视图,c代表controller,控制器。m中包含你写的业务逻辑,就是取数据的模型,v代表你显示的视图,c来控制m和v之间的关系。
Spring工作流程描述用户向服务器发送请求,请求被Spring前端控制ServeltDispatcherServlet捕获;DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。
源码分析spring-mvc启动流程
1、流程如下:用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求可以访问Servlet、哪些不能访问。就是url-pattern的作用,并且会加载springmvc.xml配置文件。
2、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。ViewReslover解析后返回具体View。DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。1DispatcherServlet响应用户。
3、SpringWebMVC处理Http请求的大致过程:\x0d\一旦Http请求到来,DispatcherSevlet将负责将请求分发。DispatcherServlet可以认为是Spring提供的前端控制器,所有的请求都有经过它来统一分发。
4、IDEA有很多的快捷键,在分析过程中建议大家多用Ctrl+Alt+B快捷键,可以快速定位到实现函数。Springbean的加载主要分为以下6步:查看源码第一步是找到程序入口,再以入口为突破口,一步步进行源码跟踪。
5、创建一个XmlWebApplicationContext,然后执行configureAndRefreshWebApplicationContext去初始化容器。此时,Controller,Interceptor等SpringMVC相关的bean就被初始化了。
6、第一步:获取SpringApplicationRunListener,然后调用他的staring方法启动监听器。第二步:根据SpringApplicationRunListeners以及参数来准备环境。第三步:创建Spring容器。第四步:Spring容器的前置处理。
springmvc怎么在启动时自己执行一个线程1、写个拦截器,在拦截器里面写要执行的操作,WEB不管访问任何路径都会先进拦截器。
2、springmvc框架提供了很多的View视图类型,包括:jspview,pdfview,jstlView、freemarkerView、pdfView等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
3、实现springMVC的多线程并发:ThreadLocal为解决多线程程序的并发问题提供了一种新的思路对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。
4、首先,你的确定数据的主键是否可以使用序列自增。如果可以那么你可以在插入数据的时候获取序列里的值,这样数据就不会重复了。
5、下面我用springMVC代替struts2去整合hibernate实现简单的员工查询功能。使用springMVC有两个配置文件需要配置,一个是applicationContext.xml、另一个是web.xml,在applicationContext.xml里面配置事务管理器以及属性注入等。
SpringMVCSpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在SpringWebFlow中。
用户发送请求至前端控制器DispatcherServlet。DispatcherServlet收到请求调用HandlerMapping处理器映射器。
springmvc是一个表现层的框架经典三层架构:表现层,service层,dao层。SpringMVC和Struts2一样,都是为了解决表现层问题的web框架,它们都是基于MVC设计模式的。
spring是框架,mvc是一种设计模式。
springmvc的工作原理是:提供了构建Web应用程序的全功能MVC模块。使用Spring可插入的MVC架构,可以选择是使用内置的SpringWeb框架还是Struts这样的Web框架。
mvc和springmvc在b/s下的实现原理1、用户发出请求,但是目的地不同虽说都是控制器,但是springmvc里面是叫前端控制器。前端控制器向处理处理映射器映射器发出请求,这一步和原来的mvc有所区别。
2、springmvc的工作原理是:提供了构建Web应用程序的全功能MVC模块。使用Spring可插入的MVC架构,可以选择是使用内置的SpringWeb框架还是Struts这样的Web框架。
3、SpringMVC框架:MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。
4、springmvc是spring的部分,其实就是spring在原有基础上,又提供了web应用的mvc模块。实现机制:struts2是基于过滤器实现的。springmvc是基于servlet实现的。
5、MVC必须先依赖Spring。Spring可以说是一个管理bean的容器,也可以说是包括很多开源项目的总称,springmvc是其中一个开源项目。MVC框架除了SpringMVC之外还有其他的框架,如structsZendFramework、.NETMVC等。
6、请求的第一站到达的是Spring的DispatcherServlet,它是一个前端控制器,工作是将用户的请求委托给其他的组件(这里是交给SpringMVC的控制器)去处理。
头秃了,二十三张图带你从源码了解SpringBoot启动流程!
源码版本
作者使用的是Spring Boot的2.4.0版本。不同版本的Spring Boot可能存在差异,建议读者与作者保持一致,以确保源码的一致性。
从哪入手
Spring Boot源码的研究起点是主启动类,即标注着`@SpringBootApplication`注解并且包含`main()`方法的类。这是Spring Boot启动的核心。
源码如何切分
SpringApplication中的静态`run()`方法是一个复杂的流程,它分为两步:创建`SpringApplication`对象和执行`run()`方法。接下来将分别介绍这两部分。
如何创建`SpringApplication`
创建`SpringApplication`的过程本质上是一个对象的生成,通过调试追踪,最终调用的构造方法如图所示。创建过程主要涉及三个阶段,我们将逐一进行深入。
设置应用类型
创建过程中的重要步骤是确定应用类型,这将直接影响项目的性质,如Web应用或非Web应用。应用类型由WebApplicationType枚举类决定,加载特定类(如DispatcherServlet)来判断。
设置初始化器
初始化器(ApplicationContextInitializer)用于在IOC容器刷新之前进行初始化操作,例如ServletContextApplicationContextInitializer。获取初始化器的方式是从SpringApplication中的方法调用开始的,最终通过`#SpringFactoriesLoader.loadSpringFactories()`方法从类路径加载。
设置监听器
监听器(ApplicationListener)负责监听特定的事件(如IOC容器刷新或关闭)。在Spring Boot中,使用SpringApplicationEvent事件来扩展监听器概念,主要在启动过程中触发。获取监听器的方式与初始化器相同,从spring.factories文件中加载。
总结
SpringApplication的构建为`run()`方法的执行铺平了道路,关键步骤包括设置应用类型、初始化器和监听器。注意,初始化器和监听器需要在spring.factories文件中声明,才能在构建过程中加载,此时IOC容器尚未创建,即使注入到容器中也不会生效。
执行`run()`方法
在构建结束后,到了启动的阶段,`run()`方法将执行一系列操作,分为八个步骤进行详细解析。
步骤1:获取并启动运行过程监听器
SpringApplicationRunListener监听器用于监听应用程序的启动过程,通过调用方法从spring.factories文件中获取运行监听器实例,并执行特定事件的广播。
步骤2:环境构建
构建过程包括加载系统和自定义配置(如application.properties),并广播事件通知监听器。
步骤3:创建IOC容器
执行容器创建过程,根据应用类型选择容器类型,此步骤仅创建容器,未进行其他操作。
步骤4:IOC容器的前置处理
这一步是容器刷新前的准备工作,关键操作是将主启动类注入容器,为后续自动化配置奠定基础。
步骤5:调用初始化器
执行构建过程中设置的初始化器,加载自定义的初始化器实现。
步骤6:加载启动类,注入容器
将主启动类加载到IOC容器中,作为自动配置的入口。
步骤7:两次事件广播
这一步涉及两次事件广播,包括ApplicationContextInitializedEvent和ApplicationPreparedEvent。
步骤8:刷新容器
容器刷新由Spring框架完成,包括资源初始化、上下文广播器等。
步骤9:IOC容器的后置处理
这一步是容器刷新后的扩展操作,通常用于打印结束日志等。
步骤:发出结束执行的事件
使用EventPublishingRunListener广播ApplicationStartedEvent事件,允许在IOC容器中注入的监听器响应。
步骤:执行Runners
Spring Boot提供了两种Runner,即CommandLineRunner和ApplicationRunner,用于定制额外操作。
总结
Spring Boot启动流程相对简洁,通过八个步骤详细描述了从创建到执行的整个过程。理解run()方法的执行流程、事件、初始化器和监听器的执行时间点是关键。