Spring之IoC容器

    spring是一个极为庞大和丰富的框架,笔者在此并不想从零开始的去讲解她。关于spring的基础概念等希望读者自行百度。文中会涉及到很多spring的源代码,我并不想在此处大量copy出来,有兴趣的读者可以自己 查看学习。再一点,阅读本文之前,读者若有一些spring的开发经验或许能更好的理解本文及spring原理。本文是在阅读了前辈大牛《SPRING技术内幕:深入解析SPRING架构与设计原理》之后撰写的,读者会在本文中找到很多书中的影子。
    
    Spring IoC容器的具体使用是构建在BeanFactory和ApplicationContext的设计与实现之上的。首先通过一个图片来了解他们之间的联系与区别,然后再仔细研究细节:
       

    从图中可以很明显的看出,BeanFactory作为基本容器在Spring IoC中的地位以及ApplicationContext作为高级形态的存在。容器是用来装载物品的,在spring中装载的就是大家熟识的bean,但我们知道,在使用spring时bean的定义或指定是在xml中配置的。spring是怎样从配置文件中获取这些bean的,并且怎样将属性值“注入”到这些实例中的?在这之中,spring有一个很重要的数据结构BeanDefinition,它抽象了我们对bean的定义,是让容器起作用的主要数据结构,spring中利用BeanDefinition来管理spring中各对象及他们之间的相互依赖关系。
     spring_IoC容器初始化的工作流程:
    Resource资源的定位(即BeanDefinition资源的定位)---->BeanDefinition载入---->BeanDefinition注册
    可以说,IoC容器的初始化就是对资源配置文件中的bean进行解析和和装载的过程。此处先提醒一下,IoC的初始化过程不包括bean依赖注入的实现。依赖注入一般发生在第一次getBean时(bean的lazyinit属性可改变bean的依赖注入过程)。
    下面以FileSystemXmlApplicationContext为例来详细说明ApplicationContext的设计原理,首先还是来了解一下FileSystemXmlApplicationContext的继承体系:


    从图可以看到,FileSystemXmlApplicationContext通过继承AbstractApplictionContext实现了ResourceLoader读入Resource定义的BeanDefinition的能力。查看FileSystemXmlApplicationContext类的源代码可以知道,这个IoC容器是由构造方法中的refresh()开启的,它的getResourceByPath()就是资源的定位。在myeclipse中查看它的调用关系及相关代码,可以得到下面的调用过程:
                                                        refreshBeanFactory()                                                                getReourceByPath()
    FileSystemXmlApplictionContext------------------>AbstractRefreshableApplicationContext-------------------->FileSystemResource

调用完成后返回FileSystemResource实例对象,通过这个对象 完成BeanDefinition的定位。如果是其他的ApplictionContext则会返回相应种类的Resource。
容器的启动是由refresh()方法开始的,这个refresh方法具体实现是在FileSystemXmlApplicationContext的基类AbstractApplicationContext中实现的。我们看一下具体的调用过程:



    在这个过程中BeanDefinitionParserDelegate的parseBeanDefinitionElement()方法可以仔细查看源代码,它是解析具体bean的地方。至此 完成了BeanDefinition的载入解析
    接下来看看 BeanDefinition的注册:还记得解析中的XmlDefinitionReader吧,完成BeanDefinition解析后紧接着就是注册了,注册是由registerBeanDefinitions()完成的。


    接下来继续看注册的具体动作,DefualtListableBeanFactory实现了BeanDefinitionRegistry接口,这个接口完成向容器的注册,注册的过程并不复杂,主要就是将BeanDefinition设置到HashMap中去,读者可以去仔细看看registerBeanDefinition()这个方法。
    至此,容器初始化的工作已完成,读者可以在源代码中看看具体的实现过程。回顾一下这个初始化的过程,它的主要工作是在IoC容器中建立BeanDefinition数据映射。有了这些映射信息作为基础,后面我们再在IoC容器中完成依赖注入。
    
    首先,依赖注入的过程是用户第一次向容器getBean()时触发的(lazy-init属性预实例化的bean除外)。从AbstractBeanFactyory类的getBean()的实现来看,这就是依赖注入的入口。下面还是通过时序图来看看这个依赖注入的过程:


    依赖注入过程中有两个很特别的方法,createBeanInstance和populateBean.createBeanInstance方法中生成了Bean所包含的java对象,populateBean则把这些Bean对象的依赖关系设置好。依赖注入的发生是在BeanWrapper的setPropertyValues中实现的,通过这一系列的复杂动作,bean属性的依赖注入便完成了。

    总结一下文章,主要是讲IoC容器初始化到依赖注入的过程,其中IoC容器初始化又分为BeanDefinition的定位、载入和注入三个步骤。在整个过程中还设计到一系列的实现类和方法,读者需要自己去浏览源代码,理解彼此之间的调用关系。另外,本文是以其中一个具体的FileSystemXmlApplicationContex为例来讲解SpringIoC容器框架设计及实现的,其它的具体实现读者可以相对应的去查看分析源代码。最后,再次感谢计文柯老师《SPRING技术内幕:深入解析SPRING架构与设计原理》的这本书,后续笔者还会继续撰写关于Spring的文章,例如SpringAOP的实现,Spring的事务处理实现等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值