引言
“ 目前,在以Java语言主导的项目中,我们会使用各种各样的框架来快速搭建应用,尤其在Java web项目中,我们会经常见到Spring的身影,大部分人只知道怎么使用它,但是不知道它真正的运行原理。本篇文章就来揭秘一下Spring框架的整体面容”
我想很多同学和我一样,在学习阅读源码前都或多或少有些疑问,在这里简单总结一下常见的问题。
看源码既费精力又无聊有啥用呢?
看完源码对我到底有哪些好处呢?
源码从那开始读?怎么读?
Spring容器启动整体流程?
带着这几个问题,来看看阅读源码是如何让我们受益的?
01
—
读源码有啥用?
从我自己的角度理解,工作一段时间以后,还是在做着重复的CRUD操作,当遇到一些比较怪异的线上故障的时候,不能像别人一样快速定位问题,总是没有头绪,眉毛胡子一把抓;遇到这样的问题多数是因为对运行的系统理解的深度不够,只知其表。所以针对这种情况,我觉得应该深入底层去理解其背后的运行原理是至关重要的。
02
—
读源码的收益是啥?
从我自己现在的体会来讲,主要有如下:
对系统整体的运行轮廓有一个比较清晰的认知,写代码更加游刃有余
学习一些框架优秀的设计思想
为跳槽做一些知识储备
03
—
源码从那开始读?
这个就比较简单了,以Spring源码为例。首先下载好源码包,写一些简单的测试用例,利用强大的debug功能调试起来,屡试不爽。在后面的源码阅读都会采用这种办法来“偷窥”其真容
04
—
Spring的IoC“轮廓”?
解决了我们的基本困惑之后,进去我们的正题,Spring到底是怎么运行起来的呢?在解答这个问题之前,我们先从宏观上看下Spring的“轮廓”,防止在读源码的时候不会一头扎进去出不来,导致很快就放弃了自己当初信誓旦旦立下的flag。我以Spring5.0.7为例展开。大家可以选择一个版本去阅读,整体流程上不会有太大的出入。下面附上我整理的Spring的流程图(画的不好,还请见谅,文末附上搭建测试工程用到的核心依赖配置文件)
对于Spring启动及bean实例化的整体流程如上图,大家先做一个简单的了解。每一步的工作也写明了,需要注意的是,比较重要的四步我使用了红色的椭圆标明了。
Spring的IoC全名是 Inversion of Control,即控制反转,大白话来讲就是由原来我们自己亲手new对象的工作交给了Spring来帮我们做了,我们只在需要指定对象的时候找Spring容器去拿就好了,就这么简单。
比较重要的几个方法我在这里在列一下:
obtainFreshBeanFactory(),其作用是创建Spring容器的工厂,并解析配置文件构建相应的BeanDefinition对象(BeanDefinition会贯穿整个源码阅读,在这里我们把它就叫做Bean定义,bean对象就是用它来实例化的)
invokeBeanFactoryPostProcessors(),其作用是调用所有实现了BeanFactoryPostProcessor接口或者是BeanDefinitionRegistryPostProcessor子接口的类,简单理解就是修改BeanDefinition定义的即可
registerBeanPostProcessors(),其作用是将实现了BeanPostProcessor接口的类注册到Spring容器中,在后面Bean实例初始化前后的时候调用其实现,简单理解就是要在bean实例初始化前后做一些增加功能即可
finishBeanFactoryInitialization(),其作用是创建所有非懒加载(非懒加载的意思就是提前加载好方便;相对应的是懒加载,就是在要使用的)
总结
本文主要阐明阅读源码能给我们带来哪些收益,以及Spring容器启动的整体流程概览。下一篇文章我们将会展开如何debug进入源码及第一个重要方法obtainFreshBeanFactory()的实现细节。坚持阅读下去,我会尽自己的努力以最直白的话去阐明Spring的流程。最后欢迎提出意见,共同进步。
附件
maven构建Spring源码调试工程用到的依赖,持续更新中
<dependencies>
<!-- spring 核心组件中的4个依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 单元测试Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>