# 前言
本文将从源码中简单探究 spring 的启动流程。
SpringFramework 版本: 6.0.3
# 过程
# ApplicationContext 的实例化
一般来说,spring 的启动无非就是根据 xml 的配置或 annotation 进行 application 的创建过程。这里以注解开发为例。Application 的创建代码如下:
ApplicationContext context = new AnnotationConfigApplicationContext("com.xxx.xxx"); |
这段代码就可以实现 spring 注解开发的 application 的启动过程,其中传入的参数为需要扫描的包名。进入这段方法的实现,代码如下:
public AnnotationConfigApplicationContext() { | |
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create"); | |
this.reader = new AnnotatedBeanDefinitionReader(this); | |
createAnnotatedBeanDefReader.end(); | |
this.scanner = new ClassPathBeanDefinitionScanner(this); | |
} | |
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { | |
this(); | |
this.register(componentClasses); | |
this.refresh(); | |
} |
首先,该方法调用了无参构造函数。在无参构造函数中,会先调用其父类 GenericApplicationContext 的构造方法,初始化一个 beanFactory=DefaultListableBeanFactory。(DefaultListableBeanFactory 是 spring 中对 BeanFactory 的一种默认实现)然后注册了几个基础的 BeanDefinition。最后通过 ClassPathBeanDefinitionScanner 加载环境变量、设置资源加载器、 注册默认的 includeFilter。
无参构造函数执行完毕后,执行了 this.register(componentClasses)
,其中 componentClasses 为配置类。此步骤就是将我们设置的配置类,解析成 beanDefinition,注册到了 beanFactory 里。
# refresh () 方法
最后则是重量级的 this.refresh()
方法。查看其源码,如下所示:
public void refresh() throws BeansException, IllegalStateException { | |
synchronized(this.startupShutdownMonitor) { | |
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); | |
// 刷新前处理;环境配置加载,必要属性验证等 | |
this.prepareRefresh(); | |
// 刷新 beanFactory,并获取一个空的 beanFactory, | |
// 这时的 beanFactory 有 6 个 beanDefinition,5 个默认的,1 个我们的配置类 | |
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); | |
// 准备 BeanFactory | |
// 1. 设置 BeanFactory 的类加载器、表达式解析器、类型转化注册器 | |
// 2. 添加三个 BeanPostProcessor,注意是具体的 BeanPostProcessor 实例对象 | |
// 3. 记录 ignoreDependencyInterface | |
// 4. 记录 ResolvableDependency | |
// 5. 添加三个单例 Bean | |
this.prepareBeanFactory(beanFactory); | |
try { | |
// 子类可以对 BeanFactory 进行进一步初始化;添加 beanFactory 的后置处理器 | |
this.postProcessBeanFactory(beanFactory); | |
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); | |
// BeanFactory 准备好了之后,执行 BeanFactoryPostProcessor,开始对 BeanFactory 进行处理 | |
// 默认情况下: | |
// 此时 beanFactory 的 beanDefinitionMap 中有 6 个 BeanDefinition,5 个基础 BeanDefinition+AppConfig 的 BeanDefinition | |
// 而这 6 个中只有一个 BeanFactoryPostProcessor:ConfigurationClassPostProcessor | |
// 这里会执行 ConfigurationClassPostProcessor 进行 @Component 的扫描,扫描得到 BeanDefinition,并注册到 beanFactory 中 | |
// 注意:扫描的过程中可能又会扫描出其他的 BeanFactoryPostProcessor,那么这些 BeanFactoryPostProcessor 也得在这一步执行 | |
this.invokeBeanFactoryPostProcessors(beanFactory); | |
// 从 BeanFactory 找出扫描得到得 BeanPostProcessor,实例化并注册到 BeanFactory 中 | |
this.registerBeanPostProcessors(beanFactory); | |
beanPostProcess.end(); | |
// 初始化 MessageSource,如果配置了一个名字叫做 “messageSource” 的 BeanDefinition | |
// 就会把这个 Bean 创建出来,并赋值给 ApplicationContext 的 messageSource 属性 | |
// 这样 ApplicationContext 就可以使用国际化的功能了 | |
this.initMessageSource(); | |
// 设置 ApplicationContext 的 applicationEventMulticaster | |
this.initApplicationEventMulticaster(); | |
// 执行子类的 onRefresh 方法 | |
this.onRefresh(); | |
// 注册 Listener | |
this.registerListeners(); | |
// 完成 beanFactory 的初始化(实例化非懒加载的单例 bean) | |
this.finishBeanFactoryInitialization(beanFactory); | |
// 发布事件 | |
this.finishRefresh(); | |
} catch (BeansException var10) { | |
if (this.logger.isWarnEnabled()) { | |
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10); | |
} | |
this.destroyBeans(); | |
this.cancelRefresh(var10); | |
throw var10; | |
} finally { | |
this.resetCommonCaches(); | |
contextRefresh.end(); | |
} | |
} | |
} |
# 总结
spring 的启动,是为了能够生成更加方便于使用的 applicationContext,从而加速开发过程。
# 参考文献
https://blog.csdn.net/BASK2312/article/details/127700231
https://blog.csdn.net/weixin_51743274/article/details/126675555