12--IoC容器简介

IoC又叫依赖注入(DI)。它描述了对象的定义和依赖的一个过程,也就是说,依赖的对象通过构造参数、工厂方法参数或者属性注入,当对象实例化后依赖的对象才被创建,当创建bean后容器注入这些依赖对象。这个过程基本上是反向的,因此命名为控制反转(IoC),它通过直接使用构造类来控制实例化,或者定义它们之间的依赖关系,或者类似于服务定位模式的一种机制。

org.springframework.beans 和 org.springframework.context 是Spring框架中IoC容器的基础, BeanFactory 接口提供一种高级的配置机制能够管理任何类型的对象。 ApplicationContext 是 BeanFactory 的子接口。它能更容易集成Spring的AOP功能、消息资源处理(比如在国际化中使用)、事件发布和特定的上下文应用层比如在网站应用中的 WebApplicationContext。

总之, BeanFactory 提供了配置框架和基本方法, ApplicationContext 添加更多的企业特定的功能。 ApplicationContext 是 BeanFactory 的一个子接口,通过解析BeanFactory的源码是了解Spring的IoC容器的一个最佳选择

在Spring中,由Spring IoC容器管理的对象叫做beans。 bean就是由Spring IoC容器实例化、组装和以其他方式管理的对象。此外bean只是你应用中许多对象中的一个。Beans以及他们之间的依赖关系是通过容器配置元数据反映出来。

1.容器概述

org.springframework.context.ApplicationContext 接口代表了Spring Ioc容器,它负责实例化、配置、组装之前的beans。容器通过读取配置元数据获取对象的实例化、配置和组装的描述信息。它配置的0元数据用xml、Java注解或Java代码表示。它允许你表示组成你应用的对象以及这些对象之间丰富的内部依赖关系。

Spring提供几个开箱即用的 ApplicationContext 接口的实现类。在独立应用程序中通常创建一个 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext实例对象。虽然XML是用于定义配置元数据的传统格式,你也可以指示容器使用Java注解或代码作为元数据格式,但要通过提供少量XML配置来声明启用对这些附加元数据格式的支持。

在大多数应用场景中,显示用户代码不需要实例化一个或多个Spring IoC容器的实例。比如在web应用场景中,在web.xml中简单的8行(或多点)样板式的xml配置文件就可以搞定(参见第3.15.4节“Web应用程序的便利的ApplicationContext实例
化”)。如果你正在使用Eclipse开发环境中的Spring Tool Suite插件,你只需要鼠标点点或者键盘敲敲就能轻松搞定这几行配置。

下图是Spring如何工作的高级展示。你应用中所有的类都由元数据组装到一起所以当 ApplicationContext 创建和实例化后,你就有了一个完全可配置和可执行的系统或应用。

这里写图片描述
2. BeanFactory

BeanFactory为Spring的IoC功能提供了底层的基础,但是它仅仅被用于和第三方框架的集成,现在对于大部分的Spring用户来说都是历史了。BeanFactory及其相关的接口,例如:BeanFactoryAware,InitializingBean,DisposableBean,在Spring
中仍然有所保留,目的就是为了让大量的第三方框架和Spring集成时保持向后兼容。通常第三方组件不会更加现代的等价物,例如:@PostConstruct 或@PreDestroy,以便可以与JDK1.4兼容,或避免依赖JSR-250。这部分提供了BeanFactory 和 ApplicationContext之间的背景差异以及用户怎样通过查找单例的模式来访问IoC容器。

3.ApplicationContext

正如本章开头所讨论的那样,org.springframework.beans.factory包提供基本的功能来管理和操作bean,包括以编程的方式。The org.springframework.context包增加了ApplicationContext接口,它继承了BeanFactory接口,除了以面向应用框架的风
格扩展接口来提供一些额外的功能。很多人以完全声明的方式使用ApplicationContext,甚至没有以编程的方式去创建它,而是依赖诸如ContextLoader等支持类来自动的实例化ApplicationContext,作为Java EE web应用程序正常启动的一部分。

为了增强BeanFactory在面向框架风格的功能,上下文的包还提供了以下的功能:

  • 通过MessageSource接口访问i18n风格的消息
  • 通过ResourceLoader接口访问类似URL和文件资源
  • 通过ApplicationEventPublisher接口,即bean实现ApplicationListener接口来进行事件发布
  • 通过HierarchicalBeanFactory接口实现加载多个(分层)上下文,允许每个上下文只关注特定的层,例如应用中的web层
4.BeanFactory or ApplicationContext?

尽量使用ApplicationContext除非你有更好的理由不用它。因为ApplicationContext包括了BeanFactory的所有功能,通常也优于BeanFactory,除非一些少数的场景,例如:在受资源约束的嵌入式设备上运行一个嵌入式应用,它的内存消耗可能至关重要,并且可能会产生字节。然而,对于大多数典型的企业级应用和系统来说,ApplicationContext才是你想使用的。Spring大量使用了BeanPostProcessor扩展点(以便使用代理等)。如果你仅仅只使用简单的BeanFactory,很多的支持功能将不会有效,例如:事务和AOP,但至少不会有额外的步骤。这可能会比较迷惑,毕竟配置又没有错。

下表列了BeanFactory 和 ApplicationContext接口和实现的一些特性:

功能 / 特点 BeanFactory ApplicationContext
Bean实例化/装配
BeanPostProcessor自动注册
BeanFactoryPostProcessor自动注册
MessageSource便捷访问(针对i18n)
ApplicationEvent 发布

用BeanFactory的实现来明确的注册一个bean的后置处理器,你需要写和下面类似的代码:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
// now register any needed BeanPostProcessor instances
MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
factory.addBeanPostProcessor(postProcessor);
// now start using the factory

当使用一个BeanFactory的实现来明确的注册一个BeanFactoryPostProcessor时,你写的代码必须和下面类似:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// now actually do the replacement
cfg.postProcessBeanFactory(factory);

在这两种情况下,明确的注册步不是很方便,这也就是为什么在大多数支持Spring的应用中,ApplicationContext的各种实现都优于BeanFactory实现的原因之一,特别是当使用BeanFactoryPostProcessors和BeanPostProcessors的时候。这些机制
实现了一些很重要的功能,例如:属性的占位替换和AOP。

5.总结

上面简单介绍了下IoC容器,BeanFactory和ApplicationContext,其中BeanFactory是IoC容器的基础,ApplicationContext是对BeanFactory的扩展,所以接下来我们以BeanFactory为入口,进行SpringIoC的分析...

附: Spring5的官方文档

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,444评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,867评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,157评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,312评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,673评论 3 289
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,802评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,010评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,743评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,470评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,696评论 2 250
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,187评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,538评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,188评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,127评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,889评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,741评论 2 274

推荐阅读更多精彩内容