我们知道Spring框架提供基于依赖注入的IOC容器,完成对象的构造、依赖注入、对象声明周期维护等功能,下面将以FileSystemXmlApplicationContext为例来分析Spring IOC容器的实现。
1.容器类图
从整体上看Spring容器可以分为两大部分:外部容器和内部容器。我们经常使用的FileSystemXmlApplicationContext、ClassPathXmlApplicationContext表现为外部容器,他们的父类都继承了ResourceLoader(资源加载),因此他们主要侧重于对外部资源的注入、解释方面的处理,而对于对象的构造、注入等声明周期维护则委托给内部对象实现,通过区分外部容器和内部容器,可以有效保护内部容器管理的bean,防止外部错误的调用破坏对象状态。
图-1 外部容器类图
图2 内部容器类图
从类图分析可以看到Spring的IOC容器可以分成两部分:外部容器和内部容器。外部容器(FileSystemXmlApplicationContext)主要负责与外部的调用进行沟通,包括接收外部的配置信息、为外部提供受容器管理的Bean、外部配置信息的解释、BeanDefinition的缓存等。内部容器(DefaultListableBeanFactory--深绿色)主要负责Bean的声明周期管理,包括Bean的注册、Bean的缓存、Bean的销毁等。
1.1 接口和类说明
类图中列出了多种类和接口,下面列出重点的进行说明。注意官方说明,翻译自API。
接口ListableBeanFactory
官方说明
BeanFactory接口的扩展,由那些能够列举它们所管理的所有bean实例的bean工厂所实现。而不是试图通过来自于客户端的by name方式的bean查找。预载所有bean definitions的BeanFactory实现可能会实现该接口。
个人理解:提供bean factory所管理bean的枚举的接口
接口HierarchicalBeanFactory
官方说明
由bean factory实现的子接口,实现了该接口的bean factory能成为一个层次结构的一部分。
个人理解:用以组织bean factory层次的一个接口。
接口ApplicationContext
官方说明:
中心接口,以提供应用程序的配置。当应用程序正在运行,这是只读的,但如果实现支持,它是允许重新加载的。
一个ApplicationContext提供如下功能:
用来访问应用程序组件的bean factory方法,其继承自ListableBeanFactory。
能以通用的方式加载文件资源,其继承自ResourceLoader。
能够向注册的监听器发布事件,其继承自ApplicationEventPublisher。
能够解析消息,支持国际化,继承自MessageSource。
继承自父上下文,后代上下文中的Definition将总能获得优先级,这意味着,例如,一个单亲上下文能够被整个应用程序使用,而每个servlet有它自己的孩子上下文,它独立于其他的servlet。
接口AutowireCapableBeanFactory
官方说明
BeanFactory接口的扩展,可以被那些有能力自动装配的bean factory实现,用以达到为存在的bean暴露此项功能的目的。
该接口不应在常见的应用程序中使用,黏合BeanFactory或者ListableBeanFactory是其典型的应用案例。
应该注意的是,该接口不应被ApplicationContext直接实现,因为应用程序代码几乎不曾被应用程序代码使用。也就是说,它也可以通过访问ApplicationContext的getAutowireCapableBeanFactory()方法从应用程序上下文中获得,即获得一个AutowireCapableBeanFactory实例。
个人理解
从接口定义的方法中可以看出,该接口主要用于自动装配bean,包括创建bean、装配bean的属性、装配bean的依赖、注册bean等。该接口对于外部的应用程序而言,几乎不需要使用,其只应用于Spring容器的内部管理,实际上只有内部bean factory实现此功能。关于内部bean factory后面会有说明。
接口ConfigurableApplicationContext
官方说明
SPI(单个程序启动)接口将会被大多数而不是全部的应用程序上下文实现,除了在ApplicationContext中的应用程序上下文客户端方法,其还提供设施来配置上下文。
配置和生命周期方法被封装在这里,以避免使他们暴漏给ApplicationContext的客户端代码。这些方法应该只用于启动和关闭代码中。
个人理解:
抽象类AbstractApplicationContext
官方说明:
ApplicationContext接口的抽象实现。其不要求配置使用的存储类型,只是简单的实现了常见上下文功能。它采用了模板方法模式,因此要求具体子类实现抽象方法。
与普通的BeanFactory相比,ApplicationContext支持检测定义在其内部的bean工厂中的特殊的bean。因此,该类能自动注册BeanFactoryPostProcessor、BeanPostProcessor、ApplicationListener,它们在上下文中都被定义为beans。
通过扩展DefaultResourceLoader实现资源加载,因此,视非URL资源路径为类路径资源(支持完整类路径资源命名,包括包路径,例如mypackage/myresource.dat),否则getResourceByPath方法需要在子类中覆写。
个人理解:
该类提供了BeanFactory的后置processor的注册、应用上下文的双亲维护、资源加载的功能。
抽象类AbstractRefreshableApplicationContext
ApplicationContext的基类的实现,其支持多次refreshs,每次创建一个内部bean工厂实例。通常(但不一定),一个上下文将会由一系列的配置定位来驱动,加载bean definations。
子类唯一需要实现的方法是loadBeanDefinitions,该方法主要是获取每次刷新调用。具体的实现应该是加载bean定义到给定的org.springframework.beans.factory.support.DefaultListableBeanFactory,通常委托给一个或多个特定的bean definition readers。
抽象类AbstractRefreshableConfigApplicationContext
官方说明
AbstractRefreshableApplicationContext的子类,增加了针对 指定的配置位置(configLocations)的常见的处理。可以作为基于XML应用程序上下文实现的基类,例如ClassPathXmlApplicationContex与FileSystemXmlApplicationContext,也可以是XmlWebApplicationContext与XmlPortletApplicationContext。
个人理解:
主要为配置文件位置的设置提供入口,即实现了setConfigLocation方法。这就提供了不依赖于Spring的且更灵活、通用的配置注入方式。
抽象类AbstractXmlApplicationContext说明:
ApplicationContext的便利基类的实现。用于提取包含bean definition信息的XML文档,该文档由XmlBeanDefinitionReader负责解释。
子类要实getConfigResources和/或getConfigLocations,此外,他们可能会覆盖
getResourceByPath钩子来解释相对路径。
类FileSystemXmlApplicationContext说明
独立的XML应用程序上下文,它从文件系统或者URLs获得上下文定义,解释普通路径为相对文件系统位置(如“MYDIR/ myfile.txt”),同时它也是有用的测试工具与独立环境。
普通路径总是会被解释为相对当前VM的工作目录,即使他们以斜线开头。(这与Servlet容器的语义是一致的。)使用一个明确的“file:”前缀,以执行一个绝对文件路径。
配置文件位置默认值可以通过getConfigLocations覆盖,配置位置可以表示为“/ MYFILES/ context.xml中”之类的具体文件,也可以像“/ MYFILES/ *- context.xml”似的Ant风格模式(org.springframework.util.AntPathMatcher)。
注意:在多个配置位置的情况下,以后的bean定义覆盖先前加载的文件中定义的。这可以通过一个额外的XML文件,来故意覆盖某些bean定义。
这是一个简单的,一站式的便利的ApplicationContext。考虑结合使用GenericApplicationContext和XmlBeanDefinitionReader提供更灵活的上下文设置。
接口ResourceLoader
加载资源(例如,类路径和文件路径)的策略接口,ApplicationContext需要提供此功能,加上扩展的ResourcePatternResolver支持。DefaultResourceLoader是该接口的独立实现,它可用于ApplicationContext以外,也可以被ResourceEditor使用。
接口ResourcePatternResolver
解释位置模式的策略接口,其扩展自ResourcePatternResolver接口。
类PathMatchingResourcePatternResolver
ResourcePatternResolver接口的实现,能够把指定的资源位置路径转化为一个或者多个匹配资源。源路径可能是一个简单的路径,它一对一映射到目标(Resource),或者可能选择性地包含特定的“classpath*:”前缀和/或者Ant-style正则表达式(由org.springframework.util.AntPathMatcher匹配)
在一般的情况,如果指定的位置路径没有以“classpath*:”前缀开始,并且未包含PathMatcher模式,解释器将通过调用ResourceLoader的getResource方法返回单一的资源。例子可包括真实的 URLs,例如file:C:/context.xml;伪URLs,例如classpath:/context.xml;简单的无前缀的路径,例如,/WEB-INF/context.xml。
2容器启动分析
2.1容器的构建
我们以FileSystemXmlApplicationContext为例来分析容器的启动过程,首先看看FileSystemXmlApplicationContext的构造函数:





















一般情况下,我们可以通过编码的方式来启动容器,例如,如下:




2.2容器的初始化
2.2.1Refresh方法分析
我们接下来分析fresh方法,该方法由FileSystemXmlApplicationContext的父类AbstractApplicationContext实现,从图1可以看到AbstractApplicationContext是ApplicationContext接口的最顶层实现。注意:方法中的子方法调用将在后面的章节中分别介绍。













































2.2.2 obtainFreshBeanFactory方法分析
该方法是在refresh方法中调用的,它主要完成了以下任务:
1.内部容器的初始化,包括对已经存在的内部容器管理的资源(缓存的singleton bean以及bean name)的销毁、内部容器的销毁、创建新的内部容器、容器的定制等;
2.资源定位解释,即把configLocations解释成一个或者多个Resource;
3.BeanDefinition加载与注册,把Resource加载解释成xml Document,然后对Document进行解释,形成BeanDefinition,并对Definition进行注册;BeanDefinition就是spring对bean的定义,在spring构造bean以及维护bean的引用关系时用到。
obtainFreshBeanFactory方法由抽象类AbstractApplicationContext定义,代码如下:











从代码中可以看到方法refreshBeanFactory与getBeanFactory都被定义为抽象方法,这是典型的模板方法模式。其中子类AbstractRefreshableApplicationContext与GenericApplicationContext都实现这些方法,接下来以AbstractRefreshableApplicationContext的实现作进一步说明。
2.2.2.1 refreshBeanFactory方法分析























容器可以有双亲(AbstractApplicationContext类的parent),每个容器下都有一个beanFactory(AbstractRefreshableApplicationContext下),该beanFactory的类型为DefaultListableBeanFactory,我们称之为内部容器。它才是真正意义上bean的管理容器,因为缓存相关bean的信息的载体是由其父类DefaultSingletonBeanRegistry负责的,这一点在下面的destroyBeans方法分析中将能看到。
refreshBeanFactory()方法详细说明:
<1>检查内部的beanFactory是否存在,如果存在则要销毁beanFactory内存在的相关资
源(关于销毁的资源参看destroyBeans方法的说明)以及关闭beanFactory;
<2>构造新的内部bean factory,并定制该工厂,定制的选项主要包括:allowBeanDefinitionOverriding(是否允许bean definition覆盖)
allowCircularReferences(是否允许bean之间循环引用)
<3>加载bean definition;
destroyBeans()方法解析
在解析之前我们先明确一件事情,spring把bean分为单实例(singleton)与原型(prototype)两种类型。对于singleton类型的bean,容器只保留一个实例,而原型类型的bean是容器每次接受请求通过defination创建的一个新实例。因此,我们都能够推断出容器是要缓存singleton bean的,事实上spring也确实这样做的。
destroyBeans主要完成了以下任务,销毁singleton beans、early singleton beans、singleton factory beans、disposable beans以及disposable beans的依赖beans。destroyBeans方法由DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry实现的,包括对singleton beans的相关缓存实现,其代码如下:
















//当调用外部容器的getBean方法时,外部容器将调用转交给DefaultListalbeBeanFactory,它会依次检查singletonObjects 、earlySingletonObjects 、singletonFactories 是否存在。















































相关推荐
### Spring的IoC容器初始化源码解析 #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented ...
1. **IoC(Inversion of Control)容器**:Spring的核心在于IoC容器,它负责管理对象的生命周期和依赖关系。在源码中,`BeanFactory`是IoC的基础接口,而`ApplicationContext`则提供了更高级的应用上下文功能。通过...
Spring 源代码分析系列涵盖了多个关键模块,包括事务处理、IoC容器、JDBC、MVC、AOP以及与Hibernate和Acegi安全框架的集成。以下是对这些知识点的详细阐述: 1. **Spring 事务处理**:Spring 提供了声明式事务管理...
《Spring IOC容器实现分析》 在Java开发领域,Spring框架无疑是使用最为广泛的轻量级框架之一,其中的核心组件就是IOC(Inversion of Control)容器。本文将深入剖析Spring的IOC容器,理解其工作原理和重要功能,以...
### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...
2. 控制反转:IoC是指应用程序的控制权从应用程序本身转移到框架,Spring容器根据配置文件动态地创建、装配和管理对象。这种设计模式使得组件之间解耦,降低了系统复杂度。 三、核心组件分析 1. ...
深入学习Spring源码,不仅能够帮助我们理解其工作原理,还能提升我们在实际项目中的问题排查能力。例如,当我们遇到Spring的依赖注入问题时,可以通过查看`BeanFactory`和`ApplicationContext`的相关源码来定位问题...
5. **搭建Spring源码阅读环境** - 从GitHub下载Spring框架的源码。 - 安装和配置 `gradle`、Idea等开发工具。 - 根据Spring的模块结构编译源码,通常需要按照 `core-oxm-context-beans-aspects-aop` 的顺序进行。...
Spring的IOC容器是其核心特性之一,它负责管理对象的生命周期和依赖关系。开发者定义Bean的配置,而IOC容器负责创建、装配和管理这些Bean。使用XML、注解或者Java配置,可以声明Bean及其依赖。这种方式使得代码更加...
Spring的IoC(Inversion of Control)容器和AOP(Aspect-Oriented Programming)支持在5.3.2中得到加强,包括对Java配置的优化,以及对注解的更精细控制。此外,还增强了Bean生命周期管理,如条件化 Bean 的创建和...
1. **spring-context-3.1.2.RELEASE.jar**:提供Spring的IoC(Inversion of Control)容器和AOP(Aspect Oriented Programming)支持,这是Spring框架的基础,为Spring Security提供了配置和事件处理能力。...
IOC容器是 Spring 框架的核心组件之一,它提供了一个统一的方式来管理应用程序中的对象。IOC 容器的主要功能是将对象的创建、管理和依赖关系解耦,使得应用程序更加灵活、可维护和可扩展。 在 Spring 中,IOC 容器...
1. **IoC(Inversion of Control)容器**:Spring的核心组件,负责管理对象的生命周期和依赖关系。在`org.springframework.beans`和`org.springframework.context`包中,我们可以看到BeanFactory和...
本项目"手写一个SpringIoc容器"旨在模仿Spring的IOC(Inversion of Control,控制反转)功能,帮助开发者深入理解Spring的工作原理,提升对依赖注入(Dependency Injection)模式的认识。 在实现自定义的Spring IOC...
通过阅读和分析Spring 1.2.6的源码,不仅可以学习到Spring的核心设计原则,还能了解到设计模式的运用,例如工厂模式、单例模式、观察者模式等。同时,这也是提升Java编程技巧和理解框架底层运作的好机会。在实际的...
`ApplicationContext`是Spring的IoC容器接口,它是访问Bean的主要入口点。`BeanFactory`是更基础的容器接口,提供更底层的控制。`BeanDefinition`则存储了Bean的配置信息。 **源码分析** 对于学习和理解Spring框架...
而Spring的IOC通过反转这一过程,将对象的创建和管理交给了IOC容器,从而降低了对象间的耦合度,提高了代码的可测试性和可维护性。 Spring的IOC容器主要有两种类型:BeanFactory和ApplicationContext。BeanFactory...
在“Spring基础:IoC容器(1)”这个主题中,我们将深入探讨Spring的核心组件——IoC容器,以及它如何管理对象的生命周期和依赖关系。 IoC(Inversion of Control),也称为控制反转,是一种设计模式,它将对象的创建...
在2022年8月14日更新的Spring源码中,我们可以深入理解其设计理念和实现机制。 Spring框架的主要组成部分包括: 1. **核心容器**:这是Spring的基础,主要包括BeanFactory和ApplicationContext。BeanFactory负责...
1. **设计模式实践**:Spring源码中大量运用了工厂模式、单例模式、观察者模式等设计模式,学习源码能加深对设计模式的理解。 2. **性能优化**:通过对源码的学习,开发者可以了解Spring如何进行性能优化,如缓存、...