Spring Bootå°è®°
1ãApplicationContextInitializerï¼å¨Springä¸ä¸æ被å·æ°ä¹åè¿è¡åå§åçæä½ãè¿ä¸ªæ¶åå·²ç»å建äºApplicationContext ï¼ä½æ¯æ²¡ærefresh()ï¼ApplicationContextInitializer对ApplicationContextè¿è¡åå§è¯æä½ã2ãSpringApplicationRunListenerï¼å¯¹ApplicationContextçè¿è¡å个æ¶æçäºä»¶è¿è¡å¹¿æï¼æ¶äºä»¶è½å¤è¢«ApplicationListeneræçå¬å°ã
3ãRunnerï¼Springä¸ä¸æåç½®å¤ç Runnerså¯ä»¥æ¯ä¸¤ä¸ªæ¥å£çå®ç°ç±»ï¼ org.springframework.boot.ApplicationRunner org.springframework.boot.CommandLineRunner å ¶å®æ²¡æä»ä¹ä¸åä¹å¤ï¼é¤äºæ¥å£ä¸çrunæ¹æ³æ¥åçåæ°ç±»åæ¯ä¸ä¸æ ·ç以å¤ãä¸ä¸ªæ¯å°è£ 好çApplicationArgumentsç±»åï¼å¦ä¸ä¸ªæ¯ç´æ¥çStringä¸å®é¿æ°ç»ç±»åãå æ¤æ ¹æ®éè¦éæ©ç¸åºçæ¥å£å®ç°å³å¯ã
SpringBootå¯å¨çæ¶åï¼ä¸è®ºè°ç¨ä»ä¹æ¹æ³ï¼é½ä¼æé ä¸ä¸ªSpringApplicationçå®ä¾ï¼ç¶åè°ç¨è¿ä¸ªå®ä¾çrunæ¹æ³ï¼è¿æ ·å°±è¡¨ç¤ºå¯å¨SpringBootã
å¨runæ¹æ³è°ç¨ä¹åï¼ä¹å°±æ¯æé SpringApplicationçæ¶åä¼è¿è¡åå§åçå·¥ä½ï¼åå§åçæ¶åä¼å以ä¸å 件äºï¼
SpringApplicationæé å®æä¹åè°ç¨runæ¹æ³ï¼å¯å¨SpringApplicationï¼runæ¹æ³æ§è¡çæ¶åä¼å以ä¸å 件äºï¼
å¨@SpringBootApplicationæ ç¾ä¸å¼å ¥äºEnableAutoConfigurationImportSelectorï¼å ¶ä¸è°ç¨äºselectImports()æ¹æ³ï¼æ¹æ³ä¸è°ç¨org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector#getCandidateConfigurationsæ¹æ³ï¼ä½¿ç¨SpringFactoryLoaderæMETA-INFæ件夹ä¸çspring.factoriesæ件ä¸EnableAutoConfiguration为keyçæ件å è½½äºã å è½½çæä»¶å ¨é¨é½æ¯java configé ç½®æ件ï¼æé»è®¤é ç½®ï¼ï¼å©ç¨@Conditional(Class<?源码 extends Condition>[]) æ ç¾ï¼å¯¹ç¸åºçbeanè¿è¡éæ©æ§çå è½½ã
æ¯è¾åºæ¬èä¸éè¦çä¸ä¸ªç±»ï¼è¿è¡å è½½äºMATE-INFä¸çspring.factories æ件
@Conditionalæ ç¾æ¯å ¨é¨Conditionalç¸å ³æ ç¾çæ ¹æºã æºç ä¸Conditionalæ ç¾ä½¿ç¨çæ¯ConditionEvaluatoræ¥è§£æï¼å¦ä¸ org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>, java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>...) org.springframework.context.annotation.ConditionEvaluator#shouldSkip(org.springframework.core.type.AnnotatedTypeMetadata, org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase)
å¨åå§åAnnotationConfigApplicationContextçæ¶åï¼å¯¹ConfigurationClassPostProcessorãAutowiredAnnotationBeanPostProcessorçç±»è¿è¡äºæ³¨åãå¦ä¸
ConfigurationClassPostProcessoræ¯ä¸ä¸ªBeanFactoryPostProcessorï¼æ以ä¼å¯¹BeanDefinitionRegistryæè BeanDefinitionå建ä¹åè¿è¡åç½®å å·¥ï¼refreshæ¹æ³ä¸ï¼å·²ç»å建äºBeanFactoryï¼å ·ä½å°è¿è¡å°åªéçæºç ï¼ã
import解æåçæ ¹æ®çæ¯ConfigurationClassPostProcessorï¼ConfigurationClassPostProcessorçå è½½è¿ç¨åèä¸é¢ 主è¦åæ为å¥@importæ ç¾æ¯å¼å ¥é ç½®çä½æ¯å´è½å¤è°ç¨Selectorçæ¹æ³ org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>) org.springframework.context.annotation.ConfigurationClassParser#processDeferredImportSelectors æ¥çå¦ä¸ï¼è°ç¨äºselectImportsæ¹æ³
Spring Boot源码解析(四)ApplicationContext准备阶段
深入解析Spring Boot中ApplicationContext的准备阶段,本文将带你从环境设置、笔记后处理到初始化器的源码执行,直至广播事件和注册应用参数等关键步骤的笔记全面解读。
环境的源码设置是准备阶段的起点,主要涉及三个步骤。笔记x9318源码首先,源码通过AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,笔记将包含实际参数的源码Environment重新配置到这些实例中,以确保ApplicationContext能够准确理解和处理后续的笔记配置信息。
紧接着,源码对ApplicationContext进行后处理。笔记这包括注册beanNameGenerator、源码设置resourceLoader和conversionService。笔记对于一般配置的源码Spring Boot应用,这些部分往往为空,因此主要执行的是设置conversionService,确保数据转换的顺利进行。
处理Initializer阶段,auto源码加密Spring Boot通过遍历META-INF/spring.factories中的initializer加载配置,执行8个预设的Initializer方法,它们负责执行特定的功能,例如增强或定制ApplicationContext行为,尽管具体实现细节未详细展开。
广播ApplicationContextInitialized和BootstrapContextClosed事件,以及注册applicationArguments和printedBanner,是准备阶段的后续操作,确保ApplicationContext能够接收外部参数并展示启动信息,同时为ApplicationContext的后续操作做准备。
在设置不支持循环引用和覆盖后,调整lazy initialization为默认不允许。Spring Boot通过配置确保依赖注入过程的高效性和稳定性,同时提供了开启懒加载的选项,允许在实际使用时加载bean,提高应用启动性能。
最后,处理重排属性的抢注id源码post processor,确保ConfigurationClassPostProcessor加载的property在正确的位置被处理,维护配置加载的逻辑顺序和依赖关系。
资源的加载是准备阶段的最后一步,将PrimarySource与所有其他源整合到allSources中,并返回一个不可修改的集合。这个过程确保了资源的高效访问和管理,为ApplicationContext的后续操作提供基础。
在完成启动类的加载后,Spring Boot通过构建BeanDefinitionLoader并配置相应的组件,将主类Application加载到Context中。这一过程是动态且高效的,确保了应用的快速启动和资源的有效管理。
至此,Spring Boot中ApplicationContext的准备阶段全面解析完成,从环境设置到启动类加载,每一个步骤都为ApplicationContext的高效运行打下了坚实的基础。接下来,我们将探讨ApplicationContext的libnettle源码下载刷新过程,敬请关注。
Springboot之分布式事务框架Seata实现原理源码分析
在SpringBoot环境下的分布式事务框架Seata实现原理涉及到了代理数据源、注册代理Bean以及全局事务拦截器等关键环节。下面我们将逐步解析其核心逻辑。
首先,Seata通过GlobalTransactionScanner来注册项目中所有带有@GlobalTransactional注解的方法类。该扫描器是一个实现了BeanPostProcessor接口的类,它能够在Spring容器初始化时进行后置处理,从而实现全局事务的管理。
GlobalTransactionScanner实际上是一个InstantiationAwareBeanPostProcessor,它在实例化Bean前执行postProcessBeforeInstantiation方法,在实例化后执行postProcessAfterInstantiation方法,并在属性填充时执行postProcessProperties方法。尽管GlobalTransactionScanner类本身并未覆盖这3个方法,但在父类的实现中,这些方法用于处理Bean的实例化和属性设置过程。
关键在于postProcessAfterInitialization方法中实现的wrapIfNecessary方法,该方法在GlobalTransactionScanner类中被重写。matlab绘图源码当方法执行到existsAnnotation方法判断类方法是否带有@GlobalTransactional注解时,如果存在则创建一个GlobalTransactionalInterceptor作为拦截器处理全局事务。
在创建代理数据源时,Seata通过DataSourceProxy对系统默认数据源进行代理处理。通过shouldSkip方法判断当前bean是否需要被代理,如果bean是SeataProxy的子类且不是DataSource的子类且不在excludes集合中,则进行代理,从而代理当前系统的默认数据源对象。
全局事务拦截器主要负责全局事务的发起、执行和回滚。在执行全局事务的方法被代理时,具体的执行拦截器是GlobalTransactionalInterceptor。该拦截器处理全局事务的逻辑,包括获取全局事务、开始全局事务、执行本地业务、提交本地事务、记录undo log、提交数据更新等步骤。其中,提交本地事务时会向TC(Transaction Coordinator)注册分支并提交本地事务,整个过程确保了分布式事务的一致性。
当全局事务中任何一个分支发生异常时,事务将被回滚。参与全局事务的组件在异常发生时执行特定的回滚逻辑,确保事务一致性。在Seata的实现中,异常处理机制确保了事务的回滚能够正确执行。
Seata还提供了XID(Transaction Identifier)的传递机制,通过RestTemplate和Feign客户端进行服务间的调用,确保分布式系统中各个服务能够共享和处理全局事务。RestTemplate在请求头中放置TX_XID头信息,而Feign客户端通过从调用链中获取Feign.Builder,最终通过SeataHystrixFeignBuilder.builder方法实现XID的传递。
在被调用端(通过Feign调用服务),Seata自动配置会创建数据源代理,使得事务方法执行时能够获取到连接对象,而这些连接对象已经被代理成DataSourceProxy。SeataHandlerInterceptor拦截器对所有请求进行拦截,从Header中获取TX_XID,参与者的XID绑定到上下文中,通过ConnectionProxy获取代理连接对象。在数据库操作中,XID绑定到ConnectionContext,执行SQL语句时通过StatementProxy或PreparedStatementProxy代理连接,从而完成全局事务的处理。
综上所述,Seata通过一系列复杂的逻辑和机制,实现了SpringBoot环境下的分布式事务管理,确保了分布式系统中数据的一致性和可靠性。
(二)springboot之spring-boot-starter-web
springboot版本:3.0.2
通过查看spring-boot-starter-web依赖文件的源码,我们可以发现其依赖的jar包包括以下内容:
spring-boot-starter-web依赖启动器的主要功能是为Web开发提供所有必要的底层依赖。
因此,在pom.xml文件中引入spring-boot-starter-web依赖启动器之后,我们就可以直接进行Web场景的开发,无需额外导入Tomcat服务器或其他Web依赖文件。当然,这些依赖文件的版本号是由spring-boot-starter-parent父依赖进行统一管理的。
详细依赖图,请访问:spring-boot-starter-web依赖图 思维导图模板_ProcessOn思维导图、流程图 获取。
springboot如何启动内置tomcat?(源码详解)
SpringBoot项目启动时,无需依赖传统Tomcat,因为内部集成了Tomcat功能。本文将深入解析SpringBoot如何通过源码启动内置Tomcat。
关键点在于`registerBeanPostProcessors`的`onRefresh`方法,它扩展了容器对象和bean实例化过程,确保单例和实例化完成。`initApplicationEventMuliticaster`则注册广播对象,与`applicationEvent`和`applicationListener`紧密相关。
文章的核心内容集中在`onRefresh()`方法,其中`createWenServer()`是关键。当`servletContext`和`webServer`为空时,会创建并初始化相关的组件,如`servletWebServerFactory`、`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`协同工作。启动过程本质上是一个链式调用,每个组件的初始化和启动都会触发下一层组件的逻辑。
2024-11-30 10:05
2024-11-30 09:13
2024-11-30 09:05
2024-11-30 08:18
2024-11-30 08:06