【SpringBoot】SpringBoot源码解析第二章 SpringBoot的run方法

fe6616eb4004c49e2d58a7bbd677f032.png

【SpringBoot】SpringBoot源码解析第一章 SpringBoot的构造方法-CSDN博客

【SpringBoot】SpringBoot源码解析第二章 SpringBoot的run方法-CSDN博客

【SpringBoot】SpringBoot源码解析第三章 SpringBoot的自动化配置-CSDN博客

【SpringBoot】SpringBoot源码解析第四章 SpringBoot的bean接口-CSDN博客

【SpringBoot】SpringBoot源码解析第五章 SpringBoot的beanDefinition收集过程-CSDN博客

【SpringBoot】SpringBoot源码解析第六章 SpringBoot的getBean方法-CSDN博客

【SpringBoot】SpringBoot源码解析第七章 SpringBoot的感悟-CSDN博客

上一章我们分析了 SpringBoot 对象的构造方法,这一章我们来分析 SpringBoot 对象的 run 方法

参考源码:<spring.boot.version>2.3.12.RELEASE</spring.boot.version>

目录

1、SpringApplication对象的run方法

1.1 createApplicationContext方法

1.2 prepareContext方法

1.3 refreshContext方法

1.3.1 invokeBeanFactoryPostProcessors方法

1.3.2 finishBeanFactoryInitialization方法

2、总结

1、SpringApplication对象的run方法

点击进入 SpringApplication 对象的 run 方法,核心代码如下

a1e60251ef22e88d0b497a4e71f83674.png

// 创建上下文环境
context = this.createApplicationContext();
// 准备上下文环境,完成对上下文环境的初始化
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文环境,是自动装配的核心,也是debugger时执行最久的语句,重点研究对象
this.refreshContext(context);

我们逐个分析上面三个和上下文 context 相关的方法

1.1 createApplicationContext方法

createApplicationContext 方法通过反射创建了一个上下文环境 context,context 实现了BeanFactory 接口,我们可以把它看作是一个 Bean 工厂,Bean 工厂的职责就是生产 Bean

4c764aafa3704b2182b38a88649e5988.png

1.2 prepareContext方法

prepareContext 方法负责初始化 context 。第一章介绍了如何获取到初始化上下文环境相关的类,拿到这些类后就可以依次调用它们的 initialize 初始化方法,调用的入口是 this.applyInitializers(context)

136ff4d45edf4374acb2e15e475d8fb0.png

1.3 refreshContext方法

refreshContext 方法顾名思义是用来刷新上下文环境的。刷新方法的调用链很长,跟踪refreshContext 方法找到 AbstractApplicationContext 的 refresh 方法

538feb3b23fc48feb155c6e5894e3c3a.png

2e9bf88255204e7798a46b26396aeec2.png

5284d358947b51f7b1a02fabb3bf304d.png

这个 refresh 方法是 Spring 装配 Bean 的核心,IOC 之道,就在其中

// 解析配置文件注解、生成beanDefinitions
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
// 完成bean工厂的初始化,并初始化所有剩余的非懒加载单例bean
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();

refresh 方法涉及的内容比较多,重点分析 invokeBeanFactoryPostProcessors 方法和 finishBeanFactoryInitialization 方法,它们的职责分别是获取 Bean 生产原料和初始化部分单例 Bean

1.3.1 invokeBeanFactoryPostProcessors方法

跟踪 invokeBeanFactoryPostProcessors 方法找到 ConfigurationClassPostProcessor 类的processConfigBeanDefinitions方法

285ff5614ce941b1bdc284e68943d516.png

4003b21dfa364e1d8ca36fa1eff97ad0.png

c6e01813f39c4692b2bb2c75e5dc975d.png

a171e433dbae4ca99dec88d5bf58fb13.png

ConfigurationClassPostProcessor 类的 processConfigBeanDefinitions 方法会收集被 @Component 等注解标记的类的 BeanDefinition,BeanDefinition 封装了生产 Bean 的原料,里面包含了类全限定名等各种和类相关的信息

调用链:
-> processConfigBeanDefinitions 
-> parser.parse(candidates);
-> parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
-> processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
-> doProcessConfigurationClass(configClass, sourceClass, filter);
-> this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
-> scanner.doScan(StringUtils.toStringArray(basePackages));

跟着调用链找到 doScan 方法,doScan 方法会扫描 @SpringBootApplication 注解内scanBasePackages 属性指定的包,未指定则默认扫描启动类所在目录下的包,收集包下所有 Bean 的 BeanDefinition,通俗来讲就是收集 Bean 原材料

825fcc6dbb82406ea662982bd20a63a5.png

1.3.2 finishBeanFactoryInitialization方法

跟踪 finishBeanFactoryInitialization 方法找到 DefaultListableBeanFactory 的 preInstantiateSingletons 方法,preInstantiateSingletons 方法调用 getBean 生成各种单例 Bean,在此处 debugger 可以看到 @Component、@Controller、@Service 等各种注解标记的类的生产过程,到这里 SpringBoot 应用基本算是初始化好了

80eaabdd35f24fc38f2783cd5271d084.pnga44c0145c05a41709ae68992826915d6.png

2、总结

SpringApplication 的 run 方法将交给 Spring 托管的 Bean 都初始化好了(可延迟加载),并且提供了上下文环境供后续使用

本章只介绍了 run 方法的大体流程,Bean 具体的生成过程和 Bean 接口相关的内容都未做详细说明,以后有空补上

下一章我们分析 @SpringBootApplication 的自动装配功能

【SpringBoot】SpringBoot源码解析第三章 SpringBoot的自动化配置-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值