做一个合格的程序猿之浅析Spring IoC源码(二)BeanFactory初始化

首先,新建项目:

pom.xml

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.   <modelVersion>4.0.0</modelVersion>  
  4.   
  5.   <groupId>org.study</groupId>  
  6.   <artifactId>spring</artifactId>  
  7.   <version>0.0.1-SNAPSHOT</version>  
  8.   <packaging>jar</packaging>  
  9.   
  10.   <name>spring</name>  
  11.   <url>http://maven.apache.org</url>  
  12.   
  13.   <properties>  
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.         <spring.version>3.2.5.RELEASE</spring.version>  
  16.     </properties>  
  17.   
  18.   <dependencies>  
  19.    <dependency>  
  20.             <groupId>junit</groupId>  
  21.             <artifactId>junit</artifactId>  
  22.             <version>4.10</version>  
  23.         </dependency>  
  24.    <dependency>  
  25.             <groupId>org.springframework</groupId>  
  26.             <artifactId>spring-orm</artifactId>  
  27.             <version>${spring.version}</version>  
  28.         </dependency>  
  29.         <dependency>  
  30.             <groupId>org.springframework</groupId>  
  31.             <artifactId>spring-expression</artifactId>  
  32.             <version>${spring.version}</version>  
  33.         </dependency>  
  34.         <dependency>  
  35.             <groupId>org.springframework</groupId>  
  36.             <artifactId>spring-aop</artifactId>  
  37.             <version>${spring.version}</version>  
  38.         </dependency>  
  39.         <dependency>  
  40.             <groupId>org.springframework</groupId>  
  41.             <artifactId>spring-beans</artifactId>  
  42.             <version>${spring.version}</version>  
  43.         </dependency>  
  44.         <dependency>  
  45.             <groupId>org.springframework</groupId>  
  46.             <artifactId>spring-context</artifactId>  
  47.             <version>${spring.version}</version>  
  48.         </dependency>  
  49.         <dependency>  
  50.             <groupId>org.springframework</groupId>  
  51.             <artifactId>spring-context-support</artifactId>  
  52.             <version>${spring.version}</version>  
  53.         </dependency>  
  54.         <dependency>  
  55.             <groupId>org.springframework</groupId>  
  56.             <artifactId>spring-test</artifactId>  
  57.             <version>${spring.version}</version>  
  58.         </dependency>  
  59.         <dependency>  
  60.             <groupId>org.springframework</groupId>  
  61.             <artifactId>spring-tx</artifactId>  
  62.             <version>${spring.version}</version>  
  63.         </dependency>  
  64.   </dependencies>  
  65. </project>  
SayService.java
  1. package org.study.spring.ioc;  
  2.   
  3. public class SayService {  
  4.       
  5.     public void say(){  
  6.         System.out.println("I am Spring");  
  7.     }  
  8.   
  9. }  
SpringIoCTest.java
  1. package org.study.spring.ioc;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. public class SpringIoCTest {  
  8.       
  9.     @Test  
  10.     public void test1(){  
  11.           
  12.          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");  
  13.          SayService sayService = (SayService)applicationContext.getBean("test");  
  14.          sayService.say();  
  15.     }  
  16.   
  17. }  

bean.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
  7.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  8.         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
  9.         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
  10.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
  11.    
  12.       
  13.     <bean id="test" class="org.study.spring.ioc.SayService"></bean>  
  14.   
  15. </beans>  

运行结果:

好了,我们以Debug模式在SpringIoCTest的第12行ClassPathXmlApplicationContext一行打上断点

在Debug之前,我们先把ClassPathXmlApplicationContext的继承图列一下

                                                                                                                                 图一

附一张BeanDefinition核心类图

                                                                                                                         图二


好了,一切准备工作好了之后,开始以debug模式运行



打开“this”构造函数

                                                                                                                                     图三

进入137行,看setConfigLocations要对我们的配置文件“bean.xml“做什么,打开setConfigLocations


上图中this.configureLations指的就是图一中用红旗②标记的configLactions,这步就理解了,给AbstractRefreshableConfigApplicationContext.java中的configLocations赋值

setConfigLocations完后,图三第139行需要进行refresh(),进入refresh(),发现refresh方法在AbstractApplicationContext.java中,也就是图一编辑的”①“标记的那个方法,打开

refresh,如图:

今天我们主要看的就是spring如何初始化beanfactory的,红色区域已经标记出,进入obtainFreshBeanFactory这个方法

                                                                                                                                图四

obtainFreshBeanFactory这个方法里面主要有2个步骤,第一个步骤537行的refreshBeanFactory(),

                                                                                                                               图五

122~125行表示如果已经有了一个容器,先销毁里面的bean然后再关闭容器,spring保证只有一个容器,然后我们看131~133行,在线程安全的状态下,为this.beanfactory赋值,那么this.beanfactory是什么呢,就是图一红旗①标记的DefaultListableBeanFactory beanFactory,现在调用方法的顺序也如图一中用①②③这种标记已经标出,refreshBeanFactory()这个方法的最终目的就是为AbstractRefreshableApplicationContext.java中DefaultListableBeanFactory beanFactory赋值,那么127~130行就是为beanFactory初始化这个容器里面的各个组件了,我们先暂时不分析127~130行代码,回到图四中538行代码,getBeanFactory(),打开getBeanFactory()

在线程安全的情况下,返回this.beanFactory,这个beanFactory是谁呢,原来就是刚刚refreshBeanFactory()方法赋值的那个AbstractRefreshableApplicationContext.java中的DefaultListableBeanFactory beanFactory,现在一切都顺理成章了,beanfactory就是这么初始化好的,然后返回的

现在我们回头分析一下图五127~130行行代码,看看beanfactory返回之前,自己完成了哪些初始化动作

127行,先创建一个beanfactory,128行设置序列化Id,129行定制化beanfactory,130行看到了我们最想看到的词”beanDefinition‘,这边终于开始加载beandefinnition了


打开loadBeanDefinitions这个方法

第82行,创建一一个XmlBeanDefinitionReader,并将beanFactory传了进去,上一节我们讲过beanFactory实现了BeanDefinitionRegistry这个接口,这时传入beanFactory,就是依据这个属性传入的


传入后,等beanDefinition好了之后就可以BeanDefinitionRegistry(beanfactory).registerBeanDefinition()了,这些都是我们上个章节讲过的,所以这里beanfactory有2种身份,接下来我们看86~92行代码,这边是对beanDefinitionReader做的一些准备初始化工作,我们不做深究,进入93行代码loadBeanDefinitions(beanDefinitionReader)




getConfigLocations这个方法我们研究过,发现它返回的正好是我们图三中setConfigLocations赋值的configLocations,即是我们传入的“bean.xml”

spring开始用我们配置的bean,xml开始初始化BeanDefinition,这边调用关系可以查看图二中标记的①②③④

最终找到XmlBeanDefinitionReader.java 中的registerBeanDefinitions(Document doc, Resource resource)方法

这个方法是返回新加入的beanDefinition的个数getRegistry()就是获取beanfactory因为beanfactory实现了BeanDefinitionRegistry,所以就可以调用getBeanDefinitionCount这个方法,我们分析493行代码registerBeanDefinitions(Document doc, XmlReaderContext readerContext),debug到DefaultBeanDefinitionDocumentReader.java中的doRegisterBeanDefinitions(Element root)这个方法



接着查看


循环bean,xml中定义的每一个元素,bean.xml中有些是标签是<bean><import>等等,分别解析



我们这边只定义了一个<bean>

这边已经看出了传入了bean.xml中的id叫做test的bean,它的class是,并且也传入了beanfactory(beanDefinition),感觉万事具备,大家看registerBeanDefinition这个方法

最后查看该bean是否有别名,如果有别名也一起注册一下,防止用户根据别名去获取bean

因为我们没有为test设置别名,所以该aliases为null,大家可以自己设置一下


好了,到此为止,我们应该知道beanFactory是怎么初始化的了,也知道beanFactory如何去加载bean.xml中的的bean了,分析的不是很好,我觉得最关键的就是图一图二显示的,理解好各个属性的关系和赋值,最后知道BeanFactory有2个角色,这样就方便大家理解Spring是如何初始化的了,大家还是自己动手理解一下吧,希望对大家有帮助~


接下来的几个章节中,我们一起理解一下依赖注入,和refresh()这个核心方法其他的方法吧


END~


转自:http://blog.csdn.net/linuu/article/details/50829981


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值