Spring IOC(一):概述
参考书籍:《Spring技术内幕》
系列文章
Spring IOC(一):概述
Spring IOC(二):初始化
Spring IOC(三):依赖注入
Spring IOC(四):相关特性
2 IOC 容器系列的设计与实现:BeanFactory
和ApplicationContext
在Spring IoC容器的设计中,我们可以看到两个主要的容器系列,一个是实现BeanFactory
接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext
应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。有了这两种基本的容器系列,基本上可以满足用户对IoC容器使用的大部分需求了。
2.1 Spring IOC 容器系列
具体什么是IOC容器呢?它在Spring框架中到底长什么样?其实对IoC容器的使用者来说,我们经常接触到的
BeanFactory
和ApplicationContext
都可以看成是容器的具体表现形式。如果深入到Spring的实现中去看,我们通常所说的IoC容器,实际上代表着一系列功能各异的容器产品,只是容器的功能有大有小,有各自的特点。我们以水桶为例,在商店中出售的水桶有大有小,制作材料也各不相同,有金属的、塑料的等,总之是各式各样的,但只要能装水,具备水桶的基本特性,那就可以作为水桶来出售,来让用户使用。这在Spring中也是一样,Spring有各式各样的IoC容器的实现供用户选择和使用。使用什么样的容器完全取决于用户的需要,但在使用之前如果能够了解容器的基本情况,那对容器的使用是非常有帮助的,就像我们在购买商品前对商品进行考察和挑选那样。从代码的角度入手,我可以看到关于这系列容器的设计情况。
在这些Spring提供的基本IoC容器的接口定义和实现的基础上,Spring通过定义BeanDefinition
来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition
抽象了我们对Bean的定义,是让容器起作用的主要数据类型。在计算机世界里,所有的功能都是建立在通过数据对现实进行抽象的基础上的。IoC容器是用来管理对象依赖关系的,对IoC容 器来说,BeanDefinition
就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition
的处理来完成的。这些BeanDefinition
就像是容器里装的水,有了这些基本数据,容器才能够发挥作用。
2.2 Spring IOC 容器的设计
IOC容器接口设计图,描述了IOC容器中的主要接口设计。
- 从接口
BeanFactory
到HierarchicalBeanFactory
,再到ConfigurableBeanFactory
是一条主要的BeanFactory
的设计路径,在这条接口设计路径中BeanFactory
定义了基本的IOC容器的规范。在这个接口定义中,包括了getBean()
这样的IOC容器的基本方法。而HierarchicalBeanFactory
接口在继承了BeanFactory
接口之后,增加了getParentBeanFactory()
的接口功能,使BeanFactory
具备了双亲IOC容器的管理功能。再接下来的ConfigurableBeanFactory
接口中主要定义了一些对BeanFactory
的配置功能,比如通过setParentBeanFactory()
设置双亲IOC容器,通过addBeanPostProcessor()
设置bean的后置处理等。通过这些接口设计的叠加,定义了BeanFactory
就是简单IOC容器的基本功能。 - 第二条接口设计主线是从
ApplicationContext
应用上下文为核心的接口设计,这里涉及的接口设计有,从BeanFactory
到ListableBeanFactory
再到ApplicationContext
再到我们常用的WebApplicationContext
或者ConfigurableApplicationContext
接口。我们常用的应用上下文基本上都是ConfigurableApplicationContext
或者WebApplicationContext
的实现。在这个接口体系中ListableBeanFactory
和HierarchicalBeanFactory
连个接口,连接BeanFactory
的接口定义和ApplicationContext
的接口定义。在ListableBeanFactory
接口中细化了很多BeanFactory
的接口功能,比如定义了String[] getBeanDefinitionNames()
接口方法,HierarchicalBeanFactory
前面已经提到过主要是增加了双亲IOC的功能,ApplicationContext
接口,它通过继承MessageSource
、ResourceLoader
、ApplicationEventPublisher
接口,在BeanFactory
简单IOC容器的基础上添加了许多对高级容器的特性的支持。 - 这里涉及的主要接口关系,而具体的IOC容器都是在这个接口体系下实现的,比如**
DefaultListableBeanFactory
,这个基本IOC容器的实现就是实现了ConfigurableListableBeanFactory
,从而成为一个简单IOC容器的实现**。像其他IOC容器,比如XmlBeanFactory
,都是基于DefaultListableBeanFactory
基础上做的拓展,同样的ApplicationContext
的实现也是如此。 - 这个接口系统是以
BeanFactory
和ApplicationContext
为核心的。而BeanFactory
又是IOC容器的最基本接口,在ApplicationContext
的设计中,一方面,可以看到它继承了BeanFactory
接口体系中的ListableBeanFactory
、AutowrieCapableBeanFactory
、HierarchicalBeanFactory
等BeanFactory
接口,具备了BeanFactory
IOC 容器的基本功能;另一方面,通过集成MessageSource
、ResourceLoader
、ApplicationEventPublisher
这些接口,BeanFactory
为ApplicationContext
赋予了更高级的IOC容器特性。对于ApplicationContext
还设计了web环境下使用的WebApplicationContext
接口。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DUyEiObN-1640346254229)(file://C:/Users/Function/AppData/Roaming/Typora/typora-user-images/1639708322628.png?lastModify=1640345739)]
2.2.1 BeanFactory的简单介绍
BeanFactory
提供的是最基本的IoC容器的功能,关于这些功能定义,我们可以在接口BeanFactory
中看到。
BeanFactory
接口定义了IoC容器最基本的形式,并且提供了IoC容器所应该遵守的最基本的服务契约 ,同时,这也是我们使用IoC容器所应遵守的最底层和最基本的编程规范,这些接口定义勾画出了IoC的基本轮廓。很显然,在Spring的 代码实现中,BeanFactory只是一个接口类,并没有给出容器的具体实现。
DefaultListableBeanFactory
, XmlBeanFactory
、 ApplicationContext
等 都可以看成是容器附加
**了某种功能的具体实现,也就是容器体系中的具体容器产品。**下面我们来看看BeanFactory
是怎样定义IoC容器的基本接口的。
2.2.2 BeanFactory的设计原理
BeanFactory
接口提供了使用IoC容器的规范。在这个基础上,Spring还提供了符合这个IoC容器接口的一系列容器的实现供开发人员使用。我们以XmlBeanFactory
的实现为例来说明简单IoC容器的设计原理。如图所示为XmlBeanFactory
设计的类继承关系。
可以看到,作为一个简单IoC容器系列最底层实现的XmlBeanFactory
,与我们在Spring应用中用到的那些上下文相比,有一个非常明显的特点: 它只提供最基本的IoC容器的功能。理解这一点有助于我们理解ApplicationContext
与基本的BeanFactory
之间的区别和联系。我们可以认为直接的BeanFactory
实现是IoC容器的基本形式,而各种ApplicationContext
的实现是IoC容器的高级表现形式。
让我们好好地看一下图中的继承关系,从中可以清楚地看到类之间的联系,它们都是IoC容器系列的组成部分。在设计这个容器系列时,我们可以从继承体系的发展上看到IoC容器各项功能的实现过程。如果要扩展自己的容器产品,最好在继承体系中检查一下,看看Spring是不是已经提供了现成的或相近的容器实现供我们参考。下面就从我们比较熟悉的XmlBeanFactory
的实现入手进行分析,来看看一个基本的IoC容器是怎样实现的。
XmlBeanFactory
继承 自DefaultListableBeanFactory
这个类,后者非常重要,是我们经常要用到的一个IoC容器的实现,比如在设计应用上下文ApplicationContext
时就会用到它。我们会看到这个**DefaultListableBeanFactory
实际上包含了基本IoC容器所具有的重要功能**,也是在很多地方都会用到的容器系列中的一个基本产品。
**在Spring中,实际上是把DefaultListableBeanFactory
作为一个默认的功能完整的IoC容器来使用的XmlBeanFactory
在继承 了 DefaultListableBeanFactory
容器的功能的同时,增加了新的功能 **这些功能很容易从XmlBeanFactory
的名字上猜到。它是一个与XML相关的BeanFactory
,也就是说它是一个可以读取以XML文件方式定义的BeanDefinition
的IoC容器。
这些实现XML读取的功能是怎样实现的呢? 对这些XML文件定义信息的处理并不是由XmIBeanFactory
直接完成的。在XmlBeanFactory
中 ,初始化了一个XmlBeanDefinitionReader
对象,有了这个Reader
对象(载入功能),那些以XML方式定义的BeanDefinition
就有了处理的地方。我们可以看到,对这些XML形式的信息的处理实际,上是由这个XmlBeanDefinitionReader
来完成的。
构造XmlBeanFactory
这个loC容器时,需要指定BeanDefinition
的信息来源,而这个信息来源需要封装成Spring中的Resource
类(定位功能)来给出。Resource
是Spring用 来封装I/O操作的类。比如,我们的BeanDefinition
信息是以XML文件形式存在的,那么可以使用像ClassPathResource res = new ClassPathResource("beans.xml");
这样具体的ClassPathResource
来构造需要的Resource,然后将Resource作为构造参数传递给XmlBeanFactory
构造函数。这样,IoC容器就可以方便地定位到需要的BeanDefinition
信息来对Bean完成容器的初始化和依赖注人过程。
XmlBeanFactory
的功能是建立在DefaultListableBeanFactory
这个基本容器的基础上的,并在这个基本容器的基础上实现了其他诸如XML读取的附加功能。对于这些功能的实现原理,看一看XmlBeanFactory
的代码实现就能很容易地理解。在XmlBeanFactory
构造方法中需要得到Resoorce
对象。对XmlBeanDefinitionReader
对象的初始化,以及使用这个对象来完成对loadBeanDefinitions
的调用,就是这个调用启动从Resource中载入BeanDefinitions
的过程,LoadBeanDefinitions
同时也是IoC容器初始化的重要组成部分。
public class XmlBeanFactory extends DefaultListableBeanFactory {private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);/*** Create a new XmlBeanFactory with the given resource,* which must be parsable using DOM.* @param resource the XML resource to load bean definitions from* @throws BeansException in case of loading or parsing errors*/public XmlBeanFactory(Resource resource) throws BeansException {this(resource, null);}/*** Create a new XmlBeanFactory with the given input stream,* which must be parsable using DOM.* @param resource the XML resource to load bean definitions from* @param parentBeanFactory parent bean factory* @throws BeansException in case of loading or parsing errors*/public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {super(parentBeanFactory);this.reader.loadBeanDefinitions(resource);}
}
我们看到XmlBeanFactory
使用了DefaultListableBeanFactory
作为基类,**DefaultListableBeanFactory
是很重要的一个IoC实现,**在其他IoC容器中,比如ApplicationContext
其实现的基本原理和XmlBeanFactory
一样,也是通过持有或者扩展DefaultListableBeanFactory
来获得基本的IoC容器的功能的。
参考XmlBeanFactory
的实现,我们以编程的方式使用DefaultListableBeanFactory
从中我们可以看到IoC容器使用的一些基本过程。尽管我们在应用中使用IoC容器时很少会使用这样原始的方式,但是了解一下这个基本过程,对我们了解IoC容器的工作原理是非常有帮助的。因为这个编程式使用容器的过程,很清楚揭示了在IoC容器实现中的那些关键的类(比如Resource
、DefaultListableBeanFactory
和BeanDefinitionReader
) 之间的相互关系,例如它们是如何把IoC容器的功能解耦的,又是如何结合在一起为IoC容器服务的等等。
ClassPathResource res = new ClassPathResource ( "beans.xml");DefaultistableBeanFactory factory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(res);
在使用IoC容器时,需要如下几个步骤:
- 创建IoC配置文件的抽象资源,这个抽象资源包含了
BeanDefinition
的定义信息。 - 创建一个
BeanFactory
,这里使用DefaultListableBeanFactory
。 - 创建一个载入
BeanDefinition
的读取器,这里使用XmlBeanDefinitionReader
来载入XML文件形式的BeanDefinition
,通过一个回调配置给BeanFactory
. - 从定义好的资源位置读入配置信息,具体的解析过程由
XmlBeanDefinitionReader
来完成。完成整个载入和注册Bean定义之后,需要的IoC容器就建立起来了。这个时候就可以直接使用IoC容器了。
2.2.3 ApplicationContext的简单介绍
ApplicationContext
是一个髙级形态意义的loC容器。可以看到ApplicationContext
还在BeanFactory
基础上扩展了其他功能。
- 支持不同的信息源。我们看到
Applicationcontext
扩展了MessageSource
接口,这些信息源的扩展功能可以支持国际化的实现,为开发多语言版本的应用提供服务。 - 访问资源。这一特性体现在对
ResourceLoader
和Resource
的支持上,这样我们可以从不同地方得到Bean定义资源。这种抽象使用户程序可以灵活地定义Bean定义信息,尤其是从不同的途径得到Bean定义信息。这在接口关系上看不出来,不过一般来说,具体ApplicationContext
都是继承了DefaultResourceLoader
的子类。因为
DefaultResourceLoader
是AbstractApplicationContext
的基类。 - 支持应用事件。继承了接口
ApplicationEventPublisher
从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean的管理提供了便利。
在AppHcationContext
中提供的附加服务。这些服务使得基本IoC容器的功能更丰富。因为具备了这些丰富的附加功能,使得ApplieationContext
与简单的BeanFactory
相比,对它的使用是一种面向框架的使用风格 ,所以一般建议在开发应用时使用ApplicationContext
作为IoC容器的基本形式。
2.2.4 ApplicationContext的设计原理
以常用的FileSystemXmlApplicationContext
的实现为例来说明ApplicationContext
容器的设计原理。
在FileSystemXmlApplicationContext
的设计中,我们看到**Applicationcontext
应用上下文的主要功能已经在 FileSystemXmlApplicationContext
的基类 AbstractXmlApplicationContext
中实现了**,在FileSystemXmlApplicationContext
中,作为一个具体的应用上下文,只需要实现和它自身设计相关的两个功能:
(1)如果应用直接使用FileSystemXmlApplicationcontext
对于实例化这个应用上下文的支持,同时启动IoC容器的refresh()过程。这在FileSystemApplicationComext
的代码实现中可以看到,代码如下:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}
这个refresh()
过程会牵涉IoC容器启动的一系列复杂操作,同时,对于不同的容器实现,这些操作都是类似的,因此在基类(AbstractApplicationContext
)中将它们封装好。所以,在FileSystemXmlApplicationContext
的设计中看到的只是一个简单的调用。
(2) 另一部分与FileSystemXmlApplicationContext
设计具体相关的功能,这部分与怎样从文件系统中加载XML的Bean定义资源有关。
通过这个过程,可以为在文件系统中读取以XML形式存在的BeanDefinitian
做准备,因为不同的应用上下文实现对应着不同的读取BeanDefinition
的方式,在FileSystemXmlApplicationContext
中的实现代码如下:
@Overrideprotected Resource getResourceByPath(String path) {if (path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}
Spring IOC(一):概述相关推荐
- Spring IOC 组件概述
IOC 概述 IOC: Inversion of Control(控制反转), 这里其实指的是: 将程序中需要使用的 POJOs, 丢入到容器中, 解析成统一的 BeanDefinition(主要基于 ...
- Spring IoC(一)IoC容器的设计与实现:BeanFactory与ApplicationContext
在写BeanFactory与ApplicationContext 之前,我想先简单聊一聊Spring IoC 容器,希望能给大家一个参考.如果你对这反面的知识比较了解,可以直接跳过. (一)Sprin ...
- 小马哥spring编程核心思想_求小马哥讲Spring栈核心编程思想 Spring IoC+Bean+Framework教程...
这次搜集了下小马哥讲Spring栈核心编程思想 Spring IoC+Bean+Framework,最强Spring全面核心实战的视频教程,有需要的朋友可以自行下载学习. 课程简介: 小马哥出手的Sp ...
- Spring IOC和DI概述
一.IOC和DI 1. IOC (Inversionof Control): 其思想是反转资源获取的方向.传统的资源查找方式要求组件向容器发起资源查找请求.作为回应,容器适时的返回资源. 而应用了IO ...
- Spring(2)——Spring IoC 详解
Spring IoC 概述 IoC:Inverse of Control(控制反转) 读作"反转控制",更好理解,不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控 ...
- Spring IoC(二)IoC容器的初始化过程
(一)IoC 容器初始化过程概述 1.1简要概述初始化过程 IoC 容器的初始化过程是通过refresh() 方法来启动的,这个方法标识着IoC 容器正式启动.具体来说,这个启动过程包括:BeanDe ...
- spring ioc原理解析
概述 Spring IOC控制反转,分为两个方面解释: 控制:对象对于内部成员的控制 反转:将之前对象管理自己内部成员,转变为ioc容器管理,目的是接耦 IOC的好处是: 无需手动创建,拿来就用 享受 ...
- java 从一个容器获取对象,如何从 Spring IoC 容器中获取对象?
前面几篇文章主要分析了 Spring IoC 容器如何初始化,以及解析和注册我们定义的 bean 信息. 其中,「Spring 中的 IoC 容器」对 Spring 中的容器做了一个概述,「Sprin ...
- Spring —— IoC 容器详解
引言 本篇博客总结自官网的<The IoC Container>,其中会结合王富强老师的<Spring揭秘>融入自己的语言和理解,争取通过这一篇文章彻底扫除spring IOC ...
最新文章
- 基于GAN模型的生成人脸重构、返老还童、看见前世今生(Age Progression/Regression)
- std::ostringstream::str()返回临时对象
- java超级简单贪吃蛇_java实现简易贪吃蛇游戏
- methodhandle_概览Java 7 MethodHandle及其用法
- html点击图片产生事件,jquery – 图像单击HTML5 Canvas中的事件
- python saml2 认证实例程序demo
- java 单文件上传_java – JIRA中的单个文件上传
- Java程序Date类型比较
- 尚硅谷和尚学堂的区别_在北京尚学堂学习的009天
- r语言去除字符串两端多余空格
- 验证码图片 java_验证码图片
- 关于ODBC使用SQL语句和调用存储过程传递参数的使用方式说明
- android 扫描照片功能,巧把安卓手机打造成扫描仪:拍照识别文档、手写笔记转PDF(图)...
- Java的System.out.println并不等于C的printf
- 布谷鸟哈希函数的参数_布谷鸟算法详细讲解
- 云计算认证哪个好?考什么内容?
- 微型计算机独立显卡,计算机显卡分为哪几类?有什么特点是?
- 悟--心智成熟的旅程
- 【JVAV】—继承、多态、抽象类
- igraph study