Spring-IOC学习-02 IOC容器初始化

上次说到spring IOC 过程中的几个重要接口: Resource, BeanDefinition, BeanDefinitionRender ,BeanFactory, ApplicationContext 

简单说了spring 的bean初始化流程:由 Resource接口的具体实现定位,读取资源文件。交给BeanfinintionRender进行bean的解析解析得到

 bean的描述对象BeanDefinition 。最后 BeanDefinitionRegister 会将已经等到的bean注册到 BeanFactory 容器中去完成bean的实例化

过程。

首先请看一个简单使用Spring的代码:

  

不知道有没有这样使用过spring呢!这正是上面所说的spring在IOC初始化时的三个步骤。这样的获取是不是让你更明白IOC的初始化脉络?

我们可以将 IOC容器初始化(bean的实例化) 过程分为 3 个部分 A:资源文件的定位  B:bean的解析,加载  C:bean的"注册"将解析后的BeanDefinition对象注册到BeanFactory

中去.(该初始化过程是不包涵Bean 的依赖注入的 ,何时完成依赖呢? )  慢慢往下看吧......

 

步骤1: BeanDefinition 资源文件的定位。

  上次说到spring 中有个重要的接口Resource 该接口负责Spring 资源文件的加载读取等操作.Reource根据不同的文件类型定位BeanDefinition。

还记得FileSystemResource,ClassPathResource这俩个子类吗?他们都是 Resource 的具体实现。分别读取不同路径下的资源文件获取BeanDefinition

  查看上面的代码Spring  通过Resource 来定位BeanDefinition资源文件,然后在使用BeanDefinitionRender来将定位的资源文件处理后得到Spring要使用的BeanDefinition

对象。因为我们使用的是单纯的容器仅仅是一个能装载 bean 的容器而已所以对于要使用什么样的Resource,什么样的BeanDefinitioRender都是由我们自己说了算的,所以这里就

很灵活了但是,因为什么都要自己定制工作量就上来了。

  为什么会这么说?还记得ApplicationContext这个NB的接口吗?找个具体实现去看看吧为啥咱们在使用spring提供的这个接口的时候不用这写额外操作呢?因为别人办理做了呀看

看别人怎么做的吧!

  

怎么样很简单吧!!!!

既然他已经得到了具体的Resource,那么FileSystemApplicationContext是怎样进行数据处理的,他是如何初始化BeanDefinition,BeanDefinitionRender的呢?查看该类并没有香瓜的代码,

仅包含多个构造的重载方法,还有这个定位资源文件的方法 getResourceByPath(....);

那么只有向他的父类找答案了! 在 AbstractRefreshableWebApplicationContext 中找到了答案! 看看FileSystemXmlApplicationContext的继承关系

 

  查看到AbstractRefreshableWebApplicationContext类的时候发了问题看一下refreshBeanFactory()方法吧!

 该方法创建了 DefaultListableBeanFactory beanFactory = createBeanFactory();  一个IOC 容器用来承载解析的BeanDefinition,容器有了那么BeanDefinition,和BeanDefinitionRender在哪里呢 ?

回想一下文章开始的时候创建IOC的代码 创建好了工厂之后接着做了什么操作,ok现在是Resource,BeanFactory  接着就该BeanDefinitionRender( factory ) ;,还有他的loadBeanDefinitions(resource);

就可以完成BeanDefinition的定位,载入了。这里依然是   loadBeanDefinitions(beanFactory);

是不是和刚才我们自己获取很相近呢?  原来BeanDefinitionRender,BeanDefinition等都是在父类中执行的载入Bean 的操作当然这是合理的因为对于bean的定位来说不同的只是文件的路径也就是path用说不

同而已,那么具体的路径交给具体的子类来实现就ok了,由子类自己来确定使用的资源。

 

2:BeanDefinition的载入,解析过程

   FileSystemXmlApplicationContext.refresh();方法初始化BeanDefinition的入口方法。该方法会调用AbstractRefreshableApplicationContext中的refreshBeanFactory();方法完成 容器的创建 BeanDefinitionRender的初始化BeanDefinition载入等操作

在refreshBeanFactory()方法中会调用 loadBeanDefinitions(beafactory); 该方法由根据不同的具体实现调用不同。此处调用的是  AbstractXmlApplicationContext中的 loadBeanDefinitions(beafactory);具体实现

最后调用loadBeanDefinitions(XmlBeaDefinitionRender);来载入bean的操作,调用了一系列 loadBeanDefinitions()方法;虽然参数不一样但是不注意的话容易出错,具体解析xml的方法是 XmlBeaDefinitionRender中的doLoadBeanDefinitions(InputSource , Resource ) ;方法完成bean的载入,解析操作。

spring 在何时将解析的bean信息封装成了自己的 BeanDefinition对象呢?

 

 这是在BeanDefinitionDocumentRender类中执行的通过 proccessBeanDefinitions( Elelment elt , BeanDefinitionParserDelegate delegate );

最终处理beanDefinition是由BeanDefinitionParserDelegate对象来执行的 处理完成后会产生一个BeanDefinitionHolder对象该对象包涵了BeanDefinition信息还有一些额外信息比如别名等信息

具体的标签解析是调用该类中的 parseBeanDefinitionElement(...) ,parseProppertyElements()....等parse方法进行的xml解析在该类中源码体现就不细说了。

完成解析后就得到了DeanDefinitionHolder对象就得到了BeanDefintion的信息。就此bean的载入就完成了!

 

3:将已经解析好的BeanDefinition注册到Ioc容器中去.

   这一步就是将上面解析得到的beanDefinition对象放到一个map中去.此时的beanDefinition已经可以使用了但是依赖关系尚未完成。

 

 

 

 

 

 

posted on 2014-02-23 12:30  java_fengyi  阅读(361)  评论(0编辑  收藏  举报