注意,看完这篇文章需要很长很长很长时间。。。
本篇文章是SpringIOC源码解析(上)的续集,上一篇文章介绍了使用XML的方式启动Spring,然后追踪了BeanFactory容器的创建、配置文件的解析、Bean的注册等。
12. finishBeanFactoryInitialization()
前方超长篇幅预警。。。
刚才我们提到了bean还没有初始化。这个方法就是负责初始化所有的没有设置懒加载的singleton bean
开始撸了
1 | protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { |
上方没有解释的代码意义往下看吧
conversionService
这种类型的bean最实用的场景就是用来将前端传过来的参数和后端的controller方法上的参数格式转换的时候使用
例如:前端要传一个String,后端使用Date接受的时候就可以这样操作
1 |
|
再搞个bean
1 | <bean id="conversionService" |
EmbeddedValueResolver
利用EmbeddedValueResolver可以很方便的实现读取配置文件的属性
1 |
|
初始化
敲黑板了,重点来了。。。
这里分析beanFactory.preInstantiateSingletons()
方法
1 | public void preInstantiateSingletons() throws BeansException { |
可以看到,不管是不是FactoryBean,最后都调用了getBean(beanName)
,继续看这个方法吧
1 | @Override |
看了上方方法我们知道了原来Spring本身只定义了两种Scope,也知道了SpringMVC的几种Scope是如何实现的了。
然后发现一开始会先判断bean存不存在,如果存在就直接返回了。如果不存在那就要接着往下看createBean
方法了
1 | protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { |
到这里第一次初始化的bean也返回了,你以为就这样结束了么。不,还有几个很重要的点
创建bean实例createBeanInstance ()
1 | protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { |
选一个无参的构造看一下吧
1 | protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { |
bean属性注入populateBean ()
1 | protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { |
getBean这一块就搞完了
13. finishRefresh()
1 | protected void finishRefresh() { |
14. resetCommonCaches()
最后还是一步还是清除缓存
15. refresh()
总结
上方用了这么长的篇幅把整个refresh()
方法的细节给梳理清楚,这里再把刚开始看的懵懵的refresh()
方法贴一下
1 |
|
总结
至此,本文到此结束。鉴于XML方式比较简单、通俗易懂,所以本文基于XML的方式大致介绍了SpringIOC的启动流程、稍微深入的讲解了Bean容器的创建以及Bean的初始化过程。这也是作者第一次阅读开源框架的源码,如文章有错误之处还请您费心指出。
鉴于现在比较流行SpringBoot和SpringCloud,下篇文章将会从基于注解的方向分析SpringIOC
推荐阅读
- SpringCloud学习系列汇总
- 为什么一线大厂面试必问redis,有啥好问的?
- 多线程面试必备基础知识汇总
- Java集合源码分析汇总-JDK1.8
- Linux常用命令速查-汇总篇
- JVM系列文章汇总
- MySQL系列文章汇总
- RabbitMQ系列文章汇总