<?xml version="1.0" encoding="UTF-8" ?> <root> <a comment="SpringApplication.run(AppMain.class, args)"> <b comment="new SpringApplication(AppMain.class).run(args)" remark="主要就是看run(args)"> <b1 comment="new SpringApplication(AppMain.class)"> 判断当前启动模式:NONE,SERVLET,REACTIVE 类加载器加载META-INF/factories,一共有两个,SpringBoot的一个,Spring的一个 C:\MavenRepository\org\springframework\boot\spring-boot\2.7.0\spring-boot-2.7.0\META-INF C:/MavenRepository/org/springframework/spring-beans/5.3.20/spring-beans-5.3.20.jar!/META-INF/spring.factories 然后做成一个Map<AppClassLoder,Map<META-INF/factories的interface,interface的实现类的集合>> 然后加载BootstrapRegistryInitializer,ApplicationContextInitializer,ApplicationListener这三个key的无参构造函数 进入SpringApplication的属性中,后面run(args)中会调用到 最后记录mainApplicationClass=AppMain.class </b1> <b2 comment="run(args)"> 记录启动时间 根据启动模式为Servlet,创建ApplicationServletEnvironment。准备环境,例如args,也就是如果你没额外配置参数,其实这些都没啥用。 配置环境相关时,有setConversionServer,例如配置的String转成Date之类一共137个 listeners.environmentPrepared(bootstrapContext, environment);把spring.profiles.active取出来了 打印banner图:如果是图片,就转成ASCII码打印出来 <createApplicationContext> ApplicationContextFactory(interceface)中有变量ApplicationContextFactory DEFAULT的初始化 =通过之前的META-INF/factories读取ApplicationContextFactory创建出org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext 在该ApplicationContextFactory构造函数中,有将注解扫描的方式的具体类设置进去this.render this.scanner以及其他的一些过滤处理之类的类的对象实例 </createApplicationContext> <prepareContext> 调用之前的environment,ApplicationContextInitializer,ApplicationListener进行处理。 然后打印应用信息:logStartupInfo(context.getParent() == null);logStartupProfileInfo(context); 将AppMain加载成一个bean(这里就涉及到详细的如何装载一个bean,可以详细看看,主要是在load(context, sources.toArray(new Object[0]));) 将之前存着的trace日志的List清空 </prepareContext> <refreshContext remark="这个是最核心的方法,归属于Spring框架而不是SpringBoot的"> <prepareRefresh> 将之前的Environment,listeners进行下处理 </prepareRefresh> <obtainFreshBeanFactory> 创建新的DefaultListableBeanFactory,有的话会销毁旧的。并且将所有bean的BeanDefinition信息加载进入BeanFactory中。 <loadBeanDefinitions remark="这个是核心">根据XML或者注解</loadBeanDefinitions> </obtainFreshBeanFactory> <prepareBeanFactory> 设置SPEL表达式解析器 addPropertyEditorRegistrar,addBeanPostProcessor ignoreDependencyInterface,registerResolvableDependency 简而言之,就是给BeanFactory设置属性值进行初始化。 </prepareBeanFactory> <postProcessBeanFactory> 给BeanFacotry的对象设置了一些值 </postProcessBeanFactory> <invokeBeanFactoryPostProcessors> 就像bean的生命周期有BeanPostProcessor,BeanFactory也有BeanFactoryPostProcessor,只不过bean的postProcessor有beforeInit和afterInit, 而BeanFacotry的postPorcessor只有after </invokeBeanFactoryPostProcessors> <registerBeanPostProcessors> Instance and register all BeanPostProcessor beans,暂时不调用BeanPostProcessor的方法 </registerBeanPostProcessors> <finishBeanFactoryInitialization> Instantiate all remaining (non-lazy-init) singletons. 核心是beanFactory.preInstantiateSingletons(); </finishBeanFactoryInitialization> prepareBeanFactory:给DefaultListableBeanFactory设置各种值 onRefresh();this.webServer = factory.getWebServer(getSelfInitializer());Tomcat容器 this.finishBeanFactoryInitialization(beanFactory);全局异常处理、druid连接池 </refreshContext></b2> </b> </a> </root>
之前有想过学习SpringBoot相关的源码,包括Spring的核心、Tomcat、MyBatis。由于多少存在点技术支撑不足,而且大多是断断续续看了一周就没看了。
经过一段时间的技术沉淀,觉得没那么难了。打算重新看起。