面试官:Spring容器启动时都做了什么?这么回答,薪资翻倍就靠它
前言
用了这么久的Spring,却没搞清楚Spring容器的内部工作机制,不知道容器启动到底做了写什么,每到面试时十个有八个倒在这个基础问题上,所以还是决定今天拿出来说一下。
AbstractApplicationContext抽象类
Spring中ApplicationContext有个抽象实现类,叫AbstractApplicationContext,在这个抽象类中,存在一个refresh()方法,这个方法定义了Spring容器在加载配置文件后的各项处理过程,很清晰的表现了Spring容器启动时所执行的各项操作。
refresh()源码简析
下面我将源码中的重要步骤进行标注出来,方便大家阅读,由于截取的源码是针对refresh()方法的,固而其中的每个子方法就不在此处详谈了,有兴趣的同学可以后面自行研究(或者大家觉得有兴趣就留言,若是感兴趣的多了笔者就再抽一篇文章去做子方法的详谈)。
源码如下图所示:
注意:细心的会发现prepareRefresh()、prepareBeanFactory(beanFactory)、postProcessBeanFactory(beanFactory)这三个方法没有被我标注出来,原因是它们扮演的是填充功能的角色,准备context的启动数据之类的功能,并不是说它们不重要,只是作为容器执行步骤来说,容器启动的关键点还是在标注的9个方法上。
9个步骤的简要说明
- 第一步,初始化BeanFactory:
根据配置文件实例化BeanFactory,Spring将配置文件的信息装入到容器的Bean 定义的注册表(BeanDefinitionRegistry)中,注意,此时Bean还没有初始化。
- 第二步,调用工厂后处理器:
利用反射机制从BeanDefinitionRegistry 中找到所有BeanFactoryPostProcessor类型的Bean,调用其postProcessBanFactory()接口方法。
- 第三步,注册Bean后处理器:
仍然利用反射,从BeanDefinitionRegistry 中找到所有BeanPostProcessor类型的Bean,将其注册到容器Bean后处理器的注册表中。
- 第四步,初始化消息源:
这一步没有特别要注意的,就是初始化容器的国际化信息资源。源码只提供了protected void initMessageSource() {//我们可以自行撸代码上去}
- 第五步,初始化应用上下文事件广播器:
Spring初始化事件广播器,用户可以在配置文件中为容器定义一个自定义的事件广播器(bean的名称要为"applicationEventMulticaster"),只需要实现ApplicationEventMulticaster即可,Spring会根据beanfactory自动获取。如果没有找到外部配置的事件广播器,则Spring使用SimpleApplicationEventMulticaster作为事件广播器。
- 第六步,初始化其他特殊的Bean:
你可以将其理解为一个钩子方法,子类可以借助这个方法执行一些特殊化处理,比如AbstractRefreshableWebApplicationContext 就是使用其执行初始化ThemeSource操作。
- 第七步,注册事件监听器:
Spring根据上下文持有的beanfactory对象,从它的BeanDefinitionRegistry中找出所有实现org.springfamework.context.ApplicationListener的bean,将BeanDefinition对象生成bean,注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。
- 第八步,初始化所有单例Bean(不包括懒加载模式的Bean):
初始化好单例的Bean之后将它们放入Spring容器的缓存中,以便后续使用。
- 第九步,发布上下文刷新事件:
创建上下文刷新事件,时间广播器负责将这些事件广播到每个注册的事件监听器中。
至此,Spring容器算是启动了。本篇其实还是大致上说了下Spring容器的启动过程,要想深刻了解其中的每一步,还需要进一步深扒一下源码。最后,想学习JAVA的小伙伴们!
请关注+私信回复:“学习”就可以拿到一份我为大家准备的300集java学习资料!
java学习资料
java学习资料