# 前言

本文将从源码中简单探究 spring 的启动流程。

SpringFramework 版本: 6.0.3

# 过程

# ApplicationContext 的实例化

一般来说,spring 的启动无非就是根据 xml 的配置或 annotation 进行 application 的创建过程。这里以注解开发为例。Application 的创建代码如下:

a
ApplicationContext context = new AnnotationConfigApplicationContext("com.xxx.xxx");

这段代码就可以实现 spring 注解开发的 application 的启动过程,其中传入的参数为需要扫描的包名。进入这段方法的实现,代码如下:

a
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

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

HuaYu 微信支付

微信支付

HuaYu 支付宝

支付宝

HuaYu 贝宝

贝宝