- 前言 -
开始《手写Spring》系列之前,想谈谈自己的一些想法。
对于每一个Java工程师来说,Spring既熟悉又陌生。熟悉,是因为我们几乎每天的工作都离不开Spring;陌生,是因为我们遇到底层的技术难题时,需要花大量的时间去分析。当然,随着Spring生态越来越完善,平时的开发工作中,好像很少会碰到底层的技术难题,就算有,可能也是一些比较简单的,看一下日志就能解决了,即使看日志不能解决的,Google一下基本就找到答案了。
那为什么还要手写Spring呢?相信每一个Java工程师都有相同的经历:从网上找了一篇《Spring源码。。。。》类似的文章,刚开始读兴致还算比较高,自己也用编译器一行行的阅读;读了一段时间之后,脑子里出现三连问:刚刚是从哪里跳进来的?这个变量什么时候初始化的?怎么和作者的截图不一样?
每一个成功的创作都是从简单到复杂的,而我们现在看的正是成功之后的复杂的Spring。既然作为普通人,直接挑战复杂是容易晕的,那为什么不从简单的开始呢?
《手写Spring》系列就是从最简单的BeanFactory接口开始,逐渐的扩展,慢慢的写出一个简易的Spring框架!!!
每一篇文章开始之前,我都会介绍这篇文章会解决哪些问题?我也会把相关的代码放在Github上。
Github地址:https://github.com/Why1214/easyspring
分支:01-BeanFactory
-
BeanFactory是如何解析xml文件的?
-
BeanDefinition对象是如何创建的?
-
如何获取到bean对象?
- 类图 -
首先,把这次相关的类图贴出来,看着类图,再去看代码会清晰很多!
- 创建单元测试用例 -
开始编码之前,我们需要做一些准备工作:
- 创建单元测试用例(测试用例是必须的,每写完一个功能,我们都需要保证不会对原有功能造成影响)
-
testGetBean() - 用来验证可以获取到对应的Bean
-
testInvalidBean() - 用来验证尝试获取不存在的Bean时,抛出BeanCreationException异常
-
testInvalidXML() - 用来验证尝试解析不存在的xml时,抛出BeanDefinitionStoreException异常
- 创建xml测试文件
- 创建 PhoneService.java
- 解析xml,生成BeanDefinition,获取Bean -
还记得我们是怎么从Spring容器里面获取一个bean对象的吗?对,就是通过ApplicationContext的getBean方法。这篇文章我们暂时不介绍ApplicationContext接口(之后会),我们首先介绍一下它的父接口BeanFactory,打开Spring的源代码,BeanFactory接口应该算是比较简单的了,因为它没有继承任何的其他接口,而且通过名字我们也可以发现,BeanFactory是Bean的工厂,既然这样,我们就能通过它获取到我们想要的bean,具体代码如下:
BeanFactory既然是一个接口,那么它就应该有自己的实现类,因此我们创建一个DefaultBeanFactory的实现类,它提供了解析xml的方法,以及创建BeanDefinition和获取bean对象的方法。那么,BeanDefinition和Bean到底有什么关联呢?其实,我们解析xml,目的就是把xml中<bean>标签的内容解析出来,解析出来之后就得有地方去存储,我们用BeanDefinition对象去存储<bean>标签的内容(我们先默认<bean>标签只有id和class属性);获取到<bean>标签的内容之后,根据class属性的值,再通过反射的技术,生成一个Bean对象是不是就变得很容易了!
首先,我们要解析xml(其实就是找到<bean>标签),生成BeanDefinition的对象,并将这个对象存储在beanDefinitionMap缓存中。这里我用了dom4j的方式进行xml解析,Spring是使用SAX对xml进行解析的。
简单说一下dom4j和SAX解析xml的不同之处(具体的可以自行Google):
-
dom4j会把整个xml文件读取到缓存里面,适合小文件解析。
-
SAX是基于事件对xml解析的,可以解析大文件。
其次,生成bean对象是通过反射的技术实现的,既然需要反射,我们就要知道bean对象的路径,而路径我们又存储在BeanDefinition对象中,所以,获取bean对象需要两个步骤:
1. 找到对应的beanDefinition对象;
2. 通过反射的技术生成bean对象。
完整的代码,大家可以去Github上下载!!!
- 总结 -
开篇算是比较简单的,主要介绍了一下xml的解析,beanDefinition创建以及bean对象的获取。我用的都是比较简单的Java语法,之后的文章会在基础类图中慢慢扩展、完善,也会有一些设计模式体现出来。