IoC容器简介
官网说明:
在核心的第7章节
1 Spring IoC 容器和 beans 简介
本章介绍了 Spring Framework implementation of the Inversion of Control(IoC)[1]原理。 IoC 也称为依赖注入(DI)。它是一个 process,其中 objects 定义它们的依赖关系,即它们使用的其他 objects,只能通过构造函数 arguments,工厂方法的 arguments,或者 object 实例在构造或从工厂方法返回后设置的 properties 。然后容器在创建 bean 时注入这些依赖项。这个 process 基本上是反向的,因此 name 控制反转(IoC),bean 本身通过使用 classes 的直接构造或诸如 Service Locator pattern 之类的机制来控制其依赖关系的实例化或位置。
org.springframework.beans和org.springframework.context包是 Spring Framework 的 IoC 容器的基础。 Bean 工厂接口提供了一种高级 configuration 机制,能够管理任何类型的 object。 ApplicationContext是BeanFactory的 sub-interface。它增加了 Spring 的 AOP features 更容易整合;消息资源处理(用于国际化),事件发布;和 application-layer 特定的上下文,例如用于 web applications。
简而言之,BeanFactory提供 configuration framework 和基本功能,ApplicationContext添加更多 enterprise-specific 功能。 ApplicationContext是BeanFactory的完整超集,在本章中专门用于 Spring 的 IoC 容器的描述。
在 Spring 中,构成 application 主干并由 Spring IoC 容器管理的 objects 称为 beans。 _ bean 是一个 object,它由 Spring IoC 容器实例化,组装和管理。否则,bean 只是 application 中许多 object 之一。 Beans 及其之间的依赖关系反映在容器使用的 configuration 元数据中。
2 容器概述
接口org.springframework.context.ApplicationContext表示 Spring IoC 容器,负责实例化,配置和组装上述 beans。容器通过读取 configuration 元数据获取有关 objects 实例化,配置和汇编的指令。 configuration 元数据以 XML,Java annotations 或 Java code 表示。它允许您表达组成您的 application 的 objects 以及这些 objects 之间丰富的相互依赖关系。
使用 Spring 为ApplicationContext提供了ApplicationContext接口的几个 implementation。在独立的 applications 中,创建ClassPathXmlApplicationContext或FileSystemXmlApplicationContext 来的实例是 common。虽然 XML 是定义 configuration 元数据的传统格式,但您可以通过提供少量 XML configuration 来声明性地启用对这些其他元数据格式的支持,从而指示容器使用 Java annotations 或 code 作为元数据格式。
在大多数 application 场景中,不需要显式用户 code 来实例化 Spring IoC 容器的一个或多个实例。
下图是 Spring 如何工作的 high-level 视图。您的 application classes 与 configuration 元数据结合使用,以便在创建和初始化ApplicationContext之后,您拥有一个完全配置且可执行的系统或 application。
图 1_.Spring IoC 容器

7.2.1 配置元数据
如上图所示,Spring IoC 容器使用一种 configuration 元数据形式;此 configuration 元数据表示您作为 application 开发人员如何告诉 Spring 容器在 application 中实例化,配置和组装 objects。
Configuration 元数据传统上以简单直观的 XML 格式提供,本章大部分内容用于传达 Spring IoC 容器的 key 概念和 features。
有关在 Spring 容器中使用其他形式的元数据的信息,请参阅:
Annotation-based configuration:Spring 2.5 引入了对 annotation-based configuration 元数据的支持。
Java-based configuration:从 Spring 3.0 开始,Spring JavaConfig 项目提供的许多 features 成为核心 Spring Framework 的一部分。因此,您可以使用 Java 而不是 XML files 定义 application classes 外部的 beans。要使用这些新的 features,请参阅
@Configuration,@Bean,@Import和@DependsOn注释。
Spring configuration 包含容器必须管理的至少一个且通常不止一个 bean 定义。 XML-based configuration 元数据显示这些 beans 在 top-level <beans/>元素内配置为<bean/>元素。 Java configuration 通常在@Configuration class 中使用@Bean带注释的方法。
这些 bean 定义对应于构成 application 的实际 objects。通常,您可以定义服务层对象,数据访问对象(DAO),表示对象(如 Struts Action实例),基础结构对象(如 Hibernate SessionFactories,JMS Queues等)。通常,不会在容器中配置 fine-grained domain objects,因为创建和加载域 objects 通常是 DAO 和业务逻辑的责任。但是,您可以使用 Spring 与 AspectJ 的 integration 来配置在 IoC 容器控制之外创建的 objects。
以下 example 显示了 XML-based configuration 元数据的基本结构:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean> <bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean> <!-- more bean definitions go here --> </beans>
id属性是一个 string,用于标识单个 bean 定义。 class属性定义 bean 的类型并使用完全限定的类名。 id 属性的 value 指的是协作 objects。用于引用协作 objects 的 XML 未在此 example 中显示;有关详细信息,请参阅依赖。
7.2.2 实例化容器
实例化 Spring IoC 容器非常简单。提供给ApplicationContext构造函数的位置路径或_path 实际上是资源 strings,它允许容器从各种外部资源(如本地文件系统,Java CLASSPATH等)加载 configuration 元数据。
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
以下 example 显示了服务层 objects (services.xml) configuration 文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- services --> <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean> <!-- more bean definitions for services go here --> </beans>
以下 example 显示了数据访问 objects daos.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean> <!-- more bean definitions for data access objects go here --> </beans>
在前面的示例中,服务层由 class PetStoreServiceImpl和两个数据访问 object 组成,类型为JpaAccountDao和JpaItemDao(基于 JPA Object/Relational 映射标准)。 property name元素引用 JavaBean property 的 name,ref元素引用另一个 bean 定义的 name。 id和ref元素之间的这种联系表达了协作 objects 之间的依赖关系。
编写 XML-based configuration 元数据
使 bean 定义 span 多个 XML files 非常有用。通常,每个单独的 XML configuration 文件都代表 architecture 中的逻辑层或模块。
您可以使用 application context 构造函数从所有这些 XML 片段加载 bean 定义。此构造函数需要多个Resource位置,如上一节中所示。或者,使用一个或多个<import/>元素来从另一个文件或 files 加载 bean 定义。例如:
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/> <bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
在前面的 example 中,外部 bean 定义从三个 files 加载:services.xml,messageSource.xml和themeSource.xml。所有位置_path 都与执行 importing 的定义文件相关,因此services.xml必须与执行 importing 的文件位于同一目录或 classpath 位置,而messageSource.xml和themeSource.xml必须位于 importing 文件位置下方的resources位置。如您所见,忽略前导斜杠,但鉴于这些_path 是相对的,最好不要使用斜杠。根据 Spring Schema,导入的 files 的内容(包括 top level <beans/>元素)必须是有效的 XML bean 定义。
使用相对“../”路径在 parent 目录中 reference files 是可能的,但不建议这样做。这样做会对当前 application 之外的文件创建依赖关系。特别是,不建议将此 reference 用于“classpath:”URL(对于 example,“classpath:../services.xml”),其中运行时解析 process 选择“最近的”classpath 根,然后查看其 parent 目录。 Classpath configuration 更改可能导致选择不同的,不正确的目录。
您始终可以使用完全限定的资源位置而不是相对的 paths:for example,“file:C:/config/services.xml”或“classpath:/config/services.xml”。但是,请注意您将 application 的 configuration 与特定的绝对位置耦合。通常最好为这样的绝对位置保持间接,例如,通过在运行时针对 JVM 系统 properties 解析的“$ {}”占位符。
import 指令是 beans 命名空间本身提供的 feature。 Spring,e.g 提供的一系列 XML 命名空间中提供了进一步 configuration features 以外的普通 bean 定义。 “context”和“util”命名空间。
2.3 使用容器
ApplicationContext是高级工厂的接口,能够维护不同 beans 及其依赖项的注册表。使用方法T getBean(String name, Class<T> requiredType),您可以检索 beans 的实例。
ApplicationContext使您能够读取 bean 定义并按如下方式访问它们:
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance
List<String> userList = service.getUsernameList();
如果需要,这些 reader 委托可以在相同的ApplicationContext上混合和匹配,从不同的 configuration 源读取 bean 定义。
然后,您可以使用getBean来检索 beans 的实例。 ApplicationContext接口有一些其他方法可以检索 beans,但理想情况下你的 application code 应该永远不会使用它们。实际上,你的 application code 根本不应该对getBean()方法有 calls,因此根本不依赖于 Spring API。例如,Spring 与 web 框架的 integration 为各种 web framework 组件(如控制器和 JSF-managed beans)提供依赖注入,允许您通过元数据声明对特定 bean 的依赖(e.g. 自动装配 annotation)。
3 BeanFactory
BeanFactory API 为 Spring 的 IoC 功能提供了基础。它的特定 contracts 主要用于与 Spring 和相关 third-party 框架的其他部分进行整合,其DefaultListableBeanFactory implementation 是 higher-level GenericApplicationContext容器中的 key 委托。
BeanFactory和相关接口(如BeanFactoryAware,InitializingBean,DisposableBean)是其他 framework 组件的重要集成点:不需要任何注释甚至反射,它们允许容器与其组件之间的非常有效的交互。 Application-level beans 可以使用相同的回调接口,但通常更喜欢通过 annotations 或通过编程 configuration 进行声明性依赖注入。
请注意,核心BeanFactory API level 及其DefaultListableBeanFactory implementation 不会对 configuration 格式或要使用的任何 component annotations 进行假设。所有这些风格都通过诸如XmlBeanDefinitionReader和AutowiredAnnotationBeanPostProcessor之类的 extensions 进行,在共享BeanDefinition objects 上作为核心元数据表示进行操作。这就是 Spring 容器如此灵活和可扩展的本质。
以下部分解释了BeanFactory和ApplicationContext容器级别之间的差异以及对引导的影响。
3.1 BeanFactory 或 ApplicationContext?
使用ApplicationContext,除非你有充分的理由不这样做,GenericApplicationContext及其子类AnnotationConfigApplicationContext作为自定义引导的 common implementations。这些是 Spring 的核心容器的主要入口点,适用于所有 common 目的:配置 files,触发 classpath 扫描,以编程方式注册 bean 定义和带注释的 classes。
因为ApplicationContext包含BeanFactory的所有功能,所以通常建议使用BeanFactory,除了需要完全控制 bean 处理的场景。在诸如GenericApplicationContext implementation 之类的ApplicationContext中,将按惯例检测到几种 beans(i.e.由 bean name 或 bean 类型),特别是 post-processors,而普通的DefaultListableBeanFactory与任何特殊的 beans 无关。
对于许多扩展容器 features,例如 annotation 处理和 AOP 代理,BeanPostProcessor 扩展点是必不可少的。如果仅使用普通DefaultListableBeanFactory,则默认情况下不会检测到并激活此类 post-processors。这种情况可能令人困惑,因为你的 bean configuration 没有任何问题;它更像是在这种情况下需要通过附加设置完全自举的容器。
以下 table lists features 由BeanFactory和ApplicationContext接口和 implementations 提供。
表格 1_.Feature Matrix
| 特征 | BeanFactory |
ApplicationContext |
|---|---|---|
| Bean实例化/装配 | 是 | 是 |
| 集成生命周期管理 | 没有 | 是 |
BeanPostProcessor自动注册 |
没有 | 是 |
BeanFactoryPostProcessor自动注册 |
没有 | 是 |
| MessageSource便捷访问(针对i18n) | 没有 | 是 |
ApplicationEvent发布机制 |
没有 | 是 |
要使用DefaultListableBeanFactory显式注册 bean post-processor,您需要以编程方式调用addBeanPostProcessor:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions // now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor()); // now start using the factory
要将BeanFactoryPostProcessor应用于普通DefaultListableBeanFactory,您需要调用其postProcessBeanFactory方法:
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);
在这两种情况下,显式注册步骤都不方便,这就是为什么各种ApplicationContext变体比 Spring-backed applications 中的普通DefaultListableBeanFactory更受欢迎,尤其是在典型企业设置中依赖BeanFactoryPostProcessor s 和BeanPostProcessor s 来扩展容器功能时。
IoC容器简介的更多相关文章
- Spring 中 IoC 容器简介
IoC 是一种通过描述来生成或者获取对象的技术,可以说 Spring 是一种基于 IoC 容器编程的框架 在一个系统中可以生成各种对象,并且这些对象都需要进行管理.为了描述这些对象关系,我们需要一个容 ...
- Spring IOC 容器 简介
Spring 容器是 Spring 框架的核心.容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁. Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件. ...
- Spring.NET的IoC容器(The IoC container)——简介(Introduction)
简介 这个章节介绍了Spring Framework的控制反转(Inversion of Control ,IoC)的实现原理. Spring.Core 程序集是Spring.NET的 IoC 容器实 ...
- Spring核心技术(一)——IoC容器和Bean简介
IoC容器和Bean简介 这章包括了Spring框架对于IoC规则的实现.Ioc也同DI(依赖注入).而对象是通过构造函数,工厂方法,或者一些Set方法来定义对象之间的依赖的.容器在创建这些Bean对 ...
- Spring源码-IOC部分-容器简介【1】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- [转]Spring IOC父子容器简介
通过HierarchicalBeanFactory接口,Spring的IoC容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的Bean,但父容器不能访问子容器的Bean.在容器内,Bean的 ...
- [Spring学习笔记 1 ] Spring 简介,初步知识--Ioc容器详解 基本原理。
一.Spring Ioc容器详解(1) 20131105 1.一切都是Bean Bean可是一个字符串或者是数字,一般是一些业务组件. 粒度一般比较粗. 2.Bean的名称 xml配置文件中,id属性 ...
- Spring框架IOC容器和AOP解析
主要分析点: 一.Spring开源框架的简介 二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置 一.S ...
- IoC 之 2.2 IoC 容器基本原理(贰)
2.2.1 IoC容器的概念 IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IoC ...
随机推荐
- Java Content Repository API 简介 转自(https://www.ibm.com/developerworks/cn/java/j-jcr/)
Java Content Repository API 简介 1 如果曾经试过开发内容管理应用程序,那么您应当非常清楚在实现内容系统时所遇到的固有难题.这个领地有点支离破碎,许多供应商都有自己的私有仓 ...
- 利用BFS解决拯救007问题 -- 数据结构
题目: 7-1 拯救007 (30 分) 在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接 ...
- scrapy之盗墓笔记三级页面爬取
#今日目标 **scrapy之盗墓笔记三级页面爬取** 今天要爬取的是盗墓笔记小说,由分析该小说的主要内容在三级页面里,故需要我们 一一解析 *代码实现* daomu.py ``` import sc ...
- frame的处理
自动化测试时,有时会定位不到某些元素,是因为这些元素在frame中,所以必须先进入到frame中,才能再去定位要定位的元素. frame是页面的框架,即在一个浏览器的窗口显示多个页面,可以是水平框架和 ...
- 01Spring基于xml的IOC配置--入门
01Spring基于xml的IOC配置 1.创建一个普通的maven工程 1.1 选择maven,不用骨架,点击下一步. 1.2 填写GroupId.ArtifactId.Version.填完点击下一 ...
- oracle链接报错shared memory realm does not exist
问题描述: 前两天能够正常链接,今天来了突然不能链接,原因不详. 处理方法: 连接linux进行如下操作: 1.sqlplus /nolog 2.conn / as sysdba 3.startup ...
- 配置MySQL服务器使得外网可以连接
https://blog.csdn.net/bird3014/article/details/78481104
- Linux日常之命令grep
命令grep简介 利用该命令在文本中查找指定的字符串,是Linux中最常用的文本处理工具之一. 命令grep与正则表达式结合使用时,功能会非常强大. 命令grep会在文本文件中按照指定的正则表达式进行 ...
- InterlliJ idea文件夹里面无法新建java文件等
这两天开始实习,因为公司用的InterlliJ idea作为开发工具,所以我这两天也开始学习如何使用这个.所以想将在操作中遇到的问题做笔记发表到上面来.也方便自己随时查阅,也希望能帮助到正在阅读的你! ...
- robotframework调用外部python多次运行拿到的都是同一个值
外部python是一个爬虫,爬取的内容的定义没有放入函数中.导致一次爬取多次使用的情况出现. 第一版函数如下: 改版后: