看源代码解决百度不到的问题
Jedis TooManyClusterRedirectionsException:太多重定向
需要掐头去尾遍历中间节点顺序查看配置或者框架内部问题,找到问题的根源在哪条操作上以及发生异常在哪个关口上,找对应抛出异常的类的引用
StringBoot关键点
- 先会用框架
- 官方文档要吃透
如何看源代码
- 先看框架架构
- 在看启动流程
- 具体的执行方法
SpringBoot启动
主要围绕:webserver管理、bean context管理(bean实体化),environment加载及管理、profile设置
- 创建SpringApplication:run方法调用SpringApplication构造函数,并调用构造体内的run方法;构造函数传入resourceLoader,并做了操作Assert,传入的primarySource就是主函数.class;进入deduceFromClasspath()函数决策出WebApplicationType的类型为Servlet(具体是查看DispatcherHandler、ServletContainer、DispatcherServlet、ConfigurableWebApplication帮助我们完成beanContext的管理)
- 初始化构造器Initializer不断调用它的Initialize方法和listner调用onApplicationEvent方法,通过getSpringFactoriesInstances获取对应的ApplicationInitializer和ApplicationListener在上一步SpringApplication实例中调用set方法赋值给SpringApplication实例,设置整个项目启动依赖的初始化器和监听器,保存在SpringApplication实例中;寻址META-INT/spring.factories;deduceMainApplicationClass决策是否存在main方法。
- 调用run方法
- 开启定时器 StopWatch:打印时间
- 根据SpringApplicationRunListeners以及参数来启动环境;初始化加载EventPhshingRunListener,然后调用EventPhshingRunListener.starting★;传入的args包装成ApplicationArguments
- 准备环境配置prepareEnvironment传入SpringApplicationRunListeners和ApplicationArguments;注意ConfigFileApplicationListener是用来加载properties文件的
- 打印banner借助printBanner
- 创建容器上下文createApplicationContext(),初始化bean容器:判断WebApplicationType返回对应的ConfigurableApplicationContext,servlet返回的是AnnotationConfigServletWebServerApplicationContext
- prepare准备容器上下文,执行之前的Initializer初始化并load主bean:prepareContext:需要把之前的环境、context、监听器之类的植入prepareContext请求,并调用applyInitializers(),然后做log日志记录;context.getBeanFactory()方法比较重要,很多bean都是通过这个beanFactory制造出来的并托管在beanFactory当中;load操作加载sources;然后进入listeners.contextLoaded(context)方法;
- refresh容器上下文,里面onRresh可以启动web server:进入ServletWebServerApplicationContext.refresh()加载资源并校验,beanFactory的获取并prepareBeanFactory里面包含Aware的组装并注册其他依赖bean;核心方法在invokeBeanFactoryPostProcessors(beanFactory)做依赖注入的管理;注解方法大部分可以在doProcessConfigurationClass中;然后进入onRefresh()方法,里面会createWebServer();最后进入finishBeanFactoryInitialization(beanFactory)进行webserver的启动startWebserver;
- afterRefresh执行初始化完成后要做的操作
- listener启动完成
- 关闭定时器
- 打印启动时间
- callRunners对所有Runners做启动
- listeners.running将所有listeners处于running状态