`

spring ioc源码学习

 
阅读更多

 

转自 http://www.iteye.com/magazines/72

 

 

本文主要以 spring ioc 容器基本代码骨架为切入点,理解 ioc 容器的基本代码组件结构,各代码组件细节剖析将放在后面的学习文章里。

 

关于IOC容器

IoC 容器:最主要是完成了完成对象的创建和依赖的管理注入等等。

先从我们自己设计这样一个视角来考虑:

所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们可配置的文件。

对象和对象关系怎么表示?

可以用 xml properties 文件等语义化配置文件表示。

描述对象关系的文件存放在哪里?

可能是 classpath filesystem ,或者是 URL 网络资源, servletContext 等。

回到正题,有了配置文件,还需要对配置文件解析。

不同的配置文件对对象的描述不一样,如标准的,自定义声明式的,如何统一? 在内部需要有一个统一的关于对象的定义,所有外部的描述都必须转化成统一的描述定义。

如何对不同的配置文件进行解析?需要对不同的配置文件语法,采用不同的解析器。

 

基于以上问题,对应过来,刚好是 spring ioc 容器抽象的的几个主要接口:

Resource

BeanDefinition

BeanDefinitionReader

BeanFactory

ApplicationContext

以上五个都是接口,都有各式各样的实现,正是这 5 个接口定义了 spring ioc 容器的基本代码组件结构。而其组件各种实现的组合关系组成了一个运行时的具体容器。

 

各代码组件详解

1.Resource

是对资源的抽象,每一个接口实现类都代表了一种资源类型,如 ClasspathResource URLResource FileSystemResource 等。每一个资源类型都封装了对某一种特定资源的访问策略。它是 spring 资源访问策略的一个基础实现,应用在很多场景。

 

 

 

 

具体可以参考文章 :

Spring 资源访问剖析和策略模式应用

http://www.ibm.com/developerworks/cn/java/j-lo-spring-resource/index.html

 

 

2.BeanDefinition

用来抽象和描述一个具体 bean 对象。是描述一个 bean 对象的基本数据结构。

3.BeanDefinitionReader

BeanDefinitionReader 将外部资源对象描述的 bean 定义统一转化为统一的内部数据结构 BeanDefinition 。对应不同的描述需要有不同的 Reader 。如 XmlBeanDefinitionReader 用来读取 xml 描述配置的 bean 对象。



 

4.BeanFactory

用来定义一个很纯粹的 bean 容器。它是一个 bean 容器的必备结构。同时和外部应用环境等隔离。 BeanDefinition 是它的基本数据结构。它维护一个 BeanDefinitions Map, 并可根据 BeanDefinition 的描述进行 bean 的创建和管理。



 

5.ApplicationContext

从名字来看叫应用上下文,是和应用环境息息相关的。没错这个就是我们平时开发中经常直接使用打交道的一个类,应用上下文,或者也叫做 spring 容器。其实它的基本实现是会持有一个 BeanFactory 对象,并基于此提供一些包装和功能扩展。为什么要这么做呢?因为 BeanFactory 实现了一个容器基本结构和功能,但是与外部环境隔离。那么读取配置文件,并将配置文件解析成 BeanDefinition ,然后注册到 BeanFactory 的这一个过程的封装自然就需要 ApplicationContext ApplicationContext 和应用环境细细相关,常见实现有 ClasspathXmlApplicationContext,FileSystemXmlApplicationContext,WebApplicationContext 等。 Classpath xml FileSystem Web 等词都代表了应用和环境相关的一些意思,从字面上不难理解各自代表的含义。

当然 ApplicationContext BeanFactory 的区别远不止于此,有:

1.  资源访问功能:在 Resource ResourceLoader 的基础上可以灵活的访问不同的资源。

2.  支持不同的信息源。

3.  支持应用事件:继承了接口 ApplicationEventPublisher ,这样在上下文中为 bean 之间提供了事件机制。

……



 

 

以上 5 个组件基本代表了 ioc 容器的一个最基本组成,而组件的组合是放在 ApplicationContext 的实现这一层来完成。

 

以ClasspathXmlApplicationContext 容器实现为例,其组合关系如下:

 


ClassPathXmlApplicationContext的refresh() 方法负责完成了整个容器的初始化。

为什么叫refresh?也就是说其实是刷新的 意思,该IOC容器里面维护了一个单例的BeanFactory,如果bean的配置有修改,也可以直接调用refresh方法,它将销毁之前的 BeanFactory,重新创建一个BeanFactory。所以叫refresh也是能理解的。

以下是Refresh的基本步骤:
1.把配置xml文件转换成resource。resource的转换是先通过ResourcePatternResolver来解析可识别格式的配置文件的路径
(如"classpath*:"等),如果没有指定格式,默认会按照类路径的资源来处理。
2.利用XmlBeanDefinitionReader完成对xml的解析,将xml Resource里定义的bean对象转换成统一的BeanDefinition。
3.将BeanDefinition注册到BeanFactory,完成对BeanFactory的初始化。BeanFactory里将会维护一个BeanDefinition的Map。

当getBean的时候就会根据调用BeanFactory,根据bean的BeanDifinition来实例化一个bean。当然根据bean的lazy-init、protetype等属性设置不同以上过程略有差别。

 

refresh()代码如下:

Java代码
  1. public   void  refresh()  throws  BeansException, IllegalStateException {  
  2.     synchronized  ( this .startupShutdownMonitor) {  
  3.         // Prepare this context for refreshing.   
  4.         prepareRefresh();  
  5.   
  6.         // Tell the subclass to refresh the internal bean factory.   
  7.         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
  8.   
  9.         // Prepare the bean factory for use in this context.   
  10.         prepareBeanFactory(beanFactory);  
  11.   
  12.         try  {  
  13.             // Allows post-processing of the bean factory in context subclasses.   
  14.             postProcessBeanFactory(beanFactory);  
  15.   
  16.             // Invoke factory processors registered as beans in the context.   
  17.             invokeBeanFactoryPostProcessors(beanFactory);  
  18.   
  19.             // Register bean processors that intercept bean creation.   
  20.             registerBeanPostProcessors(beanFactory);  
  21.   
  22.             // Initialize message source for this context.   
  23.             initMessageSource();  
  24.   
  25.             // Initialize event multicaster for this context.   
  26.             initApplicationEventMulticaster();  
  27.   
  28.             // Initialize other special beans in specific context subclasses.   
  29.             onRefresh();  
  30.   
  31.             // Check for listener beans and register them.   
  32.             registerListeners();  
  33.   
  34.             // Instantiate all remaining (non-lazy-init) singletons.   
  35.             finishBeanFactoryInitialization(beanFactory);  
  36.   
  37.             // Last step: publish corresponding event.   
  38.             finishRefresh();  
  39.         }  
  40.   
  41.         catch  (BeansException ex) {  
  42.             // Destroy already created singletons to avoid dangling resources.   
  43.             beanFactory.destroySingletons();  
  44.   
  45.             // Reset 'active' flag.   
  46.             cancelRefresh(ex);  
  47.   
  48.             // Propagate exception to caller.   
  49.             throw  ex;  
  50.         }  
  51.     }  
  52. }  

 以上的obtainFreshBeanFactory是很关键的一个方法,里面会调用loadBeanDefinition方法,如下:

Java代码
  1. protected   void  loadBeanDefinitions(DefaultListableBeanFactory beanFactory)  throws  IOException {  
  2.     // Create a new XmlBeanDefinitionReader for the given BeanFactory.   
  3.     XmlBeanDefinitionReader beanDefinitionReader = new  XmlBeanDefinitionReader(beanFactory);  
  4.   
  5.     // Configure the bean definition reader with this context's   
  6.     // resource loading environment.   
  7.     beanDefinitionReader.setResourceLoader(this );  
  8.     beanDefinitionReader.setEntityResolver(new  ResourceEntityResolver( this ));  
  9.   
  10.     // Allow a subclass to provide custom initialization of the reader,   
  11.     // then proceed with actually loading the bean definitions.   
  12.     initBeanDefinitionReader(beanDefinitionReader);  
  13.     loadBeanDefinitions(beanDefinitionReader);  
  14. }  

 LoadBeanDifinition方法很关键,这里特定于整个IOC容器,实例化了一个XmlBeanDefinitionReader来解析Resource文件。关于Resource文件如何初始化和xml文件如何解析都在

Java代码
  1. loadBeanDefinitions(beanDefinitionReader);  

 里面的层层调用完成,这里不在累述。

小结 

Spring 的扩展性是毋庸置疑的,学习 spring 的设计是一个很好的实践理论结合。主要个人觉得有几点:

1.  框架顶层的设计有着很好的抽象,遵循面向接口编程的规范。 Resource BeanFactory ApplicationContext 都是非常好的接口抽象,非常明确的定义了该组件的一些功能。

2.  利用组合模式。

3.  个组件的实现里大量使用了模板方法模式,提升了同一组件代码的复用性。

4.  各种设计保留了扩展的接口,很多基于 spring 的框架都可以很容易的介入实现了自己的一些扩展。

5.  框架里采用里很多经典的设计模式,如代理、装饰、策略等等。

分享到:
评论

相关推荐

    Spring IoC源码深度剖析开源架构源码2021.pdf

    标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...

    Spring IOC源码解读

    Spring IOC,即Inversion of Control(控制反转),是Spring框架的核心特性之一,它负责管理和装配应用程序中的对象。...理解并掌握Spring的IOC源码,对于深入学习Spring框架以及提升系统设计能力具有重要意义。

    基于Maven构建的Spring IoC源码实例

    在"基于Maven构建的Spring IoC源码实例"中,我们可以学到如何使用Maven搭建Spring项目,并通过Spring IoC实现组件间的依赖注入。以下是这个实例中可能包含的关键知识点: 1. **Maven项目结构**:了解标准的Maven...

    Java进阶之SpringIoC源码深度剖析共19页.pd

    【标题】"Java进阶之SpringIoC源码深度剖析共19页.pd" 提供的是一项关于Java开发中的高级主题,特别是针对Spring框架的依赖注入(Inversion of Control,IoC)部分的深入研究。Spring IoC是Spring框架的核心特性之一...

    Spring4 IOC 示例源码

    在这个示例源码中,我们可以深入理解并学习如何在实际项目中运用Spring的IOC容器来管理对象的生命周期和依赖关系。 1. **Spring 框架介绍** Spring是一个开源的Java平台,它提供了全面的企业级应用开发解决方案,...

    spring IOC学习源码

    `.idea`文件夹是IntelliJ IDEA的工作空间配置,与Spring源码学习关联不大,通常在提交代码时会被忽略。 为了深入理解Spring IOC,我们需要关注以下几个源码的关键部分: 1. **BeanDefinitionReader**:读取XML配置...

    spring ioc

    标题 "Spring IOC" 描述了我们讨论的核心主题——Spring 框架中的依赖注入(Inversion of Control,简称 IOC)...通过深入学习和理解 Spring 源码,我们可以更好地掌握这个强大的工具,并在日常开发中发挥更大的作用。

    老王读spring-ioc源码分析&测试代码.zip

    老王读 Spring IoC 系列文章的源码分析&测试代码 Spring IoC 源码分析,帮助大家学习 Spring 源码,更加了解 Spring 的底层 博客专栏地址:https://blog.csdn.net/wang489687009/category_11269905.html

    小读spring ioc源码(一)——整体介绍

    《Spring IOC源码解析(一)——整体介绍》 在深入理解Spring框架的过程中,源码分析是不可或缺的一环。本文将对Spring的IOC(Inversion of Control,控制反转)容器的源码进行初步探讨,旨在帮助读者从整体上把握...

    SpringIOC示例源代码

    Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它负责管理对象的生命周期和依赖关系。在这个示例源代码中,我们...通过学习和理解这些文件,你可以更好地掌握Spring框架的核心理念和使用方式。

    spring IOC

    关于【源码】,深入理解Spring的IOC源码可以帮助我们更好地掌握其实现原理。Spring采用工厂模式创建Bean,同时使用反射和CGLIB动态代理技术来处理对象的实例化和依赖注入。当我们声明一个Bean时,Spring会通过反射...

    Spring的IoC容器初始化源码解析

    ### Spring的IoC容器初始化源码解析 #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented ...

    SpringIOC+SpringMVC学习笔记

    个人学习spring框架时记录的笔记,纯手敲,SpringIOC+SpringMVC学习笔记,有兴趣的可以参考

    Spring Ioc(依赖注入)入门例子--属性注入

    通过阅读这些源码,我们可以学习如何定义bean,声明依赖,以及如何让Spring容器根据配置来创建和管理对象。 总的来说,掌握Spring的IoC和DI是成为一名熟练的Java开发者必备的技能。理解并应用这些概念可以显著提高...

    深入解析Spring IoC:源码与实践指南

    理解Spring IoC的源码实现对于Java开发者至关重要,它能帮助我们更深入地了解Spring框架的工作原理,从而更高效地利用Spring进行编程。通过阅读和分析源码,我们可以学习到如何配置和管理Bean,以及如何自定义Bean的...

    模拟Spring的IOC

    理解并模拟Spring的IOC机制对于深入学习Spring以及提升软件设计能力具有重要意义。 **1. 控制反转(IOC)概念** 控制反转是一种设计思想,它将对象的创建和管理权交给容器,而不是由对象自身负责。这样可以降低对象...

    Spring IoC应用开源架构源码2021.pdf

    通过源码学习Spring IoC的实现,可以帮助开发者深入理解Spring的工作原理,提升开发技能,更好地利用Spring解决实际问题。开源源码的学习提供了这样的机会,让开发者能够查看并分析Spring框架的内部实现,进一步提升...

    Spring高级源码学习笔记.zip

    源码学习是提升编程技能的重要途径,尤其是在理解复杂框架如Spring的工作原理时。本笔记旨在深入解析Spring的高级源码,帮助程序员从应用层面过渡到源码级的理解。 Spring的核心组件包括Bean容器、AOP代理、数据...

    Spring学习笔记&源码

    本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程,旨在帮助学习者深入理解和实践Spring框架。 笔记部分可能会涵盖以下内容: 1. **Spring概述**:介绍Spring框架的历史、特点和主要...

    Spring之IOC示例

    在IT行业中,Spring框架是Java开发领域中一个极为...通过阅读《Spring之IOC示例》这篇博客(博文链接:https://huangminwen.iteye.com/blog/1041298),可以更深入地理解Spring的IOC机制,并学习如何在实际项目中应用。

Global site tag (gtag.js) - Google Analytics