首页 > 代码库 > Spring IOC的实现
Spring IOC的实现
来源:知乎 https://www.zhihu.com/question/21035417/answer/142858103
著作权归作者所有。
Spring IOC的实现部分,主要分为三个部分:
第一步:
Resouce:首先我们需要获取beanDefinition的资源,我们将通过Spring的resource接口获得bean的资源,这一步也叫做bean资源的定位,下面是Spring内置的一些典型实现,当然,你也可以根据自己的需要实现自己的resource:
ClassPathResource可用来获取类路径下的资源文件。假设我们有一个资源文件test.txt在类路径下,我们就可以通过给定对应资源文件在类路径下的路径path来获取它,new ClassPathResource(“test.txt”)。
FileSystemResource可用来获取文件系统里面的资源。我们可以通过对应资源文件的文件路径来构建一个FileSystemResource。FileSystemResource还可以往对应的资源文件里面写内容,当然前提是当前资源文件是可写的,这可以通过其isWritable()方法来判断。FileSystemResource对外开放了对应资源文件的输出流,可以通过getOutputStream()方法获取到。
UrlResource可用来代表URL对应的资源,它对URL做了一个简单的封装。通过给定一个URL地址,我们就能构建一个UrlResource。
ByteArrayResource是针对于字节数组封装的资源,它的构建需要一个字节数组。
ServletContextResource是针对于ServletContext封装的资源,用于访问ServletContext环境下的资源。ServletContextResource持有一个ServletContext的引用,其底层是通过ServletContext的getResource()方法和getResourceAsStream()方法来获取资源的。
InputStreamResource是针对于输入流封装的资源,它的构建需要一个输入流。
第二步:
第二步叫做bean Resource的解析:就是将我们获取到的resource转换成bean存在于Spring中的数据结构,也就是BeanDefinition,在我自己实现的Spring中,beanDefinition实现的比较简单,主要有bean的作用域,持有bean的class对象,以及用一个String数组保存的它所依赖的bean的名字,现在也只能支持singleton和prototype两种作用域;(Spring中beanDefinition的实现类并不多,大家可以去看下这部分的源代码,弄懂了beanDefinition,IOC部分就明白一半了)
第三步:
在第二步bean资源的解析完成之后,我们需要将beanDefinition注册到我们的工厂,用一个map集合进行保存;注册完成之后,工厂的初始化也就完成了,接下来就是我们熟悉的通过getBean方法从容器中获取我们所需要的bean了;getBean方法也正式触发Spring依赖注入的起点,在这里也是有两个问题:
1.如何保证Spring bean的创建顺序,即被依赖的bean总是要先被完整的创建
2.当bean之间出现了循环依赖又该如何解决?
在这里我用了组合模式,将Spring中的bean分为两种,一种是依赖于其他bean的bean,一种是独立的bean,它并不依赖于其他的bean,采用了递归的方式进行解决;(这部分说起来比较复杂,后面在贴代码进行分析)
题主水平有限,对Spring的理解也很浅,如果讲有错误的地方,欢迎指正
我自己实现的一个Spring地址:MySixGod/SpringImpl_v2.0 ,目前较好的解决了依赖的问题,但是依赖注入的方式单一,方法不灵活,对于属性的命名,set方法的命名都有严格的要求,因为在此之前重心放在beanDefinition上,后续的话会实现别名接口,添加更多的注入方式,争取能完成一个小而美的简单版Spring吧
Spring IOC的实现