昔闻洞庭水,今上岳阳楼。
1 前言
在日常 web
开发中 Spring
是经常使用的开发框架,在前文中已经分享了Springboot 启动流程分析,其中涉及自动装配的原理即启动流程尚未涉及,在本文中将继续分享 Spring
启动流程的关键点,一共涉及12个关键的技术点。自动装配指的是 Spring
容器自动将相互依赖的 bean
建立联系的过程,开发者无需再 xml
或者 java
配置中显示地指定所有依赖, Spring
通过特定规则自动寻找并注入所需要的依赖。
2 refresh 核心流程
刷新上下文 refreshContext(context)
-> refresh()
是 Spring
框架容器启动的核心,最终调用 AbstractApplicationContext.refresh()
方法,在 tomcat
容器中通过上下文 ServletWebServerApplicationContext
来实现。

-
1 准备刷新
prepareRefresh
, 设置容器启动的时间,初始化配置,以及配置信息。在springboot
环境准备中,已经获取到了systemEnvironment
和systemProperties
对象,这里通过initServletPropertySources
方法添加servletContextInitParams
和servletConfigInitParams
属性。接下来通过validateRequiredProperties
进行配置信息必填项校验,比如数据库连接账户密码,redis 连接等信息。 最后会设置系统的监听器和初始化既完成环境准备。 -
2
obtainFreshBeanFactory
获取BeanFactory
。在Spring Web
开发中使用ClassPathXmlApplicationContext
容器,会使用refreshBeanFactroy
方法重新构造BeanFactory
,读取xml
配置文件构建BeanDefinition
。在springboot
开发中由于采用了ServletWebServerApplicationContext
作为容器,已经加载了配置信息构造了BeanFactory
,这里并不执行任何动作。 -
3 准备容器
prepareBeanFactory
配置标准特性,这里会注册类加载器、配置文件处理器,表达式解析器(ClassLoader、PropertyEditRegister、BeanExpressionResolver
)。此外还会加载ApplicationContextAwareProcessor
和ApplicationListenerDetector
两个后置处理器,前者是用来解析 Aware 接口,后者用来处理自定义监听器的注册和销毁。接下来会将 beanFactory 和 ApplicationContext 对象注册到特殊对象池resolvableDependencies
(注册非标准Bean
定义的依赖项的机制,是在DefaultListableBeanFactory
中)。最后会将environment
和systemProperties
注册到单例池中,即singletonObjects
(其在DefaultSingletonBeanRegistry
中定义,它的子类是DefaultListableBeanFactory
)。 -
4
postProcessBeanFactory
这里会对BeanFactory
进行额外的配置和修改,这里主要定义了包括request、session
在内的Servlet
相关作用域以及注册ServletRequest、HttpSession、ServletResponse
对象到单例池中。 -
5
invokeBeanFactoryPostProcessors
这里主要是调用Bean
的后置处理器。其中最主要的是加载后置处理器ConfigurationClassPostProcessor
,它的作用是加载所有@configuration
的配置类,同时检索所有的Bean
扫描路径ComponentScans
, 通过ClassPathBeanDefinitionScanner.doScan
扫描每个类,并将其封装成BeanDefinition
对象放在Bean
定义池beanDefinitionMap
中。 同时也会通过processImports
方法将@Import @Bean
的方法加入到Bean
定义池中。 -
6
registerBeanPostProcessors
检索容器中的所有后置处理器BeanPostProcessor
,会按照优先级(PriorityOrdered Ordered
)进行排序,并将排序好的后置处理器注册到beanPostProcessors
中。后置处理器会在Bean
初始化之前和之后执行相应的逻辑。 -
7
initMessageSource
初始化messageSource
对象。这个步骤是为了实现提示信息的国际化而使用,可以在resources
中自定义message.properties
信息进行覆盖,实现多语言的切换配置。 -
8
initApplicationEventMulticaster
初始化消息广播器applicationEventMulticaster
。 有了这个配置就可以通过publishEvent
方法进行事件发布。 -
9
onRefresh
构建并启动web
服务器。如果是spring
需要使用tomcat
进行启动,对于springboot
来讲,需要查找实现了ServletWebServerFactory
这个接口的应用服务器Bean
, 默认也是内置的tomcat
。 接下来通过createWebServer
方法构造一个Tomcat
对象,通过start
方法进行启动,这样容器内部的web
服务器就启动了。 -
10
registerListeners
查找容器中的所有监听器并注册到第8步的消息广播器中。 -
11
finishBeanFactoryInitialization
通过该方法可以生产所有业务代码中的Bean
信息,整体分为构造对象、填充属性、初始化、使用、销毁等5个步骤。生产完成的对象会放置在单例池singletonObjects
中。 -
12
finishRefresh
构造并注册生命周期管理器LifecycleProcessor
, 同时调用所有实现了该接口的类,在开始时调用start
方法,在容器关闭时调用stop
方法。最后发布一个容器刷新完成的事件ContextRefreshedEvent
,这个自动装配的流程就完成了。
3 Bean 构建
在 2.11 finishBeanFactoryInitialization
中,实例化所有非懒加载的单例 bean。这是一个非常重要的步骤。
- 1 首先会遍历所有的
Bean
定义,即BeanDefinitionNames
对象。 - 2 对于所有符合条件的
Bean
(单例、非抽象、非懒加载),通过getBean() -> doGetBean() -> createBean() -> doCreateBean()
,最终通过createBeanInstance
方法,通过反射方式创建bean
对象。 - 3 在
doCreateBean()
中,自动装配即填充属性 (populateBean
) 发生:AutowiredAnnotationBeanPostProcessor
在这里工作,注入依赖。 - 4 然后执行初始化回调 (
initializeBean - @PostConstruct, InitializingBean.afterPropertiesSet, init-method
)。这里还会有实现Aware
接口和实现了后置处理器的逻辑。
这里只是简单介绍其核心内容,其中还会涉及到大家知道的三级缓存,以及循环依赖的问题,在后续文章中会详细解读。
4 关键节点
通过分析以上的启动流程,我们可以根据业务需要,自定义事件监听器替代简单的异步场景、后置处理器用于对 Bean
进行修改或者添加属性。也可以自定义实现 webServer
的构建,按照自己的业务需要构建 tomcat
。
了解了自动装配的原理,我们可以根据业务需要,实现自己的 starter
。其中最核心的方法就是自动装配的原理: SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, classLoader)
从所有依赖的 META-INF/spring.factories
文件中加载并注册。
5 总结
在本文中主要讲述了自动装配原理即 IOC
创建流程,在掌握了 spring
自动装配的原理之后,在业务开发中遇到需要对 spring
进行扩展的场景中,能够从容应对,得心应手,能够更好的完成任务,做到胸有成竹。