这是自己学习及缕清思路的学习笔记 具体的可能会比较乱 之后本人会去整理
平时我们都是通过springapplication.run去启动一个应用
spring boot 启动的时候 可以有多启动器 也就是多个class 去获取配置
然后springboot在启动的时候 会获取启动类型 也就是springboot容器的启动类型 然后去判断springboot以何种服务器类型启动 例如tomcat webflux webmvc servlet等
springboot的多class启动 主要是获取class上的注解 通过注解去获取starter启动信息
spring支持自定义类加载器 当spring容器中没有自定义类加载器时 将会采用启动类加载器(app classloader)去加载spring容器中所需要的类
当spring容器是由系统类加载器加载时 那么spring默认会采用系统类加载器去加载spring容器所需要的类
之后spring将会采用刚刚所获得的类加载器 去加载spring初始化程序 在springboot中 获取ApplicationContextInitializer的实现类作为初始化程序
接着就是加载spring的listener 加载方式与上一步相同
这里发现一个误区 一直以来认为springboot获取main方法是通过springapplication.run传入的class来获取run 刚刚发现其实并不是如此 springboot获取main方法是通过获取当前启动栈信息来获取当前的main方法的启动类地址 这里用了一个方式 通过新建异常 获取异常栈的方式 在异常栈里边找到main的类信息来获取启动类地址
之后加载spring的 EventPublishingRunListener 加载方式与前两步相同 之后再初始化SpringApplicationRunListeners 里边通过一个EventObject的子类ApplicationStartingEvent去监听事件
通过ApplicationStartingEvent初始化ResolvableType
之后获取listener列表
之后spring将会采用获取线程池的方式去执行listener 如无线程池 则使用单线程运行listener
接下来是查看几个listener的区别
LoggingApplicationListener:
获取当前类加载器 将默认的日志管理器全定限类型去询问类加载器 是否可以加载到 过滤掉加载不到的 之后获取第一个符合条件的日志管理器进行使用 如果找不到 则将会抛出异常
BackgroundPreinitializer所做的事:
启动线程 后台执行初始化程序 后台执行的初始化程序一共有六个 分别是:
ConversionServiceInitializer
ValidationInitializer
MessageConverterInitializer
MBeanFactoryInitializer
JacksonInitializer
CharsetInitializer
LiquibaseServiceLocatorApplicationListener、DelegatingApplicationListener:
这俩监听器暂时似乎没有用到
spring有一个命令解析器 当我们在run一个spring程序时 命令后边可能会带一些类似--server.port --spring.active.profile之类的参数 spring的命令解析器就用来做这个的 在springboot启动程序中 发现这个命令解析器使用的是SimpleCommandLineArgsParser 通过将命令行中带的参数截取--或者=去截取 之后放到一个类似map的一个列表 CommandLineArgs
spring自身还初始化了很多转换器 这方面对转换器的整理做的还是比较好的
值转换器:
集合转换器:
其他的转换器
formater:
今天先到这 记录到springboot 2.1.4
SpringApplication 306行
SpringApplication 346行
SpringApplication 487行
AbstractEnvironment 493行