## 4.2 容器概述
org.springframework.context.ApplicationContext 接口代表了 Spring 的 IoC 容器,负责实例化,配置和装配上述的 bean。容器获得指示来实例化某对象,配置并装 配,这都是通过读取配置元数据实现的。配置元数据在 XML 中,Java 注解或 Java 代码中来 表示。它允许你表达编写应用程序的对象,还有对象间丰富的相互依存的关系。
ApplicationContext 接口的一些实现使用 Spring [开箱的支持。在独立的应用程序 中 , 通 常 是 来 创 建](http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html) [ClassPathXmlApplicationContext](http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html) [或](http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html) [FileSystemXmlApplicationContext](http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html) 的实例。XML 是定义配置元数据的传统格式,你 可以指示容器使用 Java 的注解或是代码作为元数据的格式,提供少量的 XML 配置声明来开 启对这些额外的元数据格式的支持。
在很多应用场景中,明确的用户代码不需要实例化一个或者多个 Spring IoC 容器的实例。 比如,在 Web 应用场景中,在应用程序的 web.xml 中简单的八(左右)行样板 J2EE 描述 符 XML 文件通常就够了(参考 4.14.4 节“对 Web 应用程序方便的应用上下文实例化”)。如 果你正使用 [SpringSource](http://www.springsource.com/produts/sts) [的工具套件](http://www.springsource.com/produts/sts),Eclipse [支持的开发环境或者是](http://www.springsource.org/roo) [Spring ROO](http://www.springsource.org/roo) 这样的样板 配置,就可以容易地被创建,点几下鼠标或按键就可以了。
下图是 Spring 如何工作的高级别视图。你的应用程序类联合配置元数据,所以在 ApplicationContext 被创建和实例化后,就得到了一个完全配置的可执行系统或程序。
![image](https://box.kancloud.cn/2016-01-25_56a58526acc3c.jpg)
Spring 的 IoC 容器
### 4.2.1 配置元数据
正如上图所示,Spring 的 IoC 容器处理配置元数据的一种形式;这个配置元数据代表了 你作为应用开发人员是如何告诉 Spring 容器在你的应用程序中来实例化,配置并装配对象 的。
配置元数据传统上是以直观的 XML 格式提供的,这是本章的大部分内容使用它来传达 Spring IoC 容器关键概念和功能。
> ![](https://box.kancloud.cn/2016-01-25_56a58526bb420.gif)
> 注意
> 基于 XML 的元数据并不是唯一的配置元数据格式。这种配置元数据真正写入时,Spring 的 IoC 容器本身和这种格式完全脱钩。
关于 Spring 容器使用元数据格式的信息,可以参考:
基于注解的配置(4.9 节):Spring 2.5 引入了对基于注解元数据的支持。
基于 Java 的配置(4.12 节):从 Spring 3.0 开始,很多由 Spring JavaConfig 项目提供的特 性称为 Spring Framework 的核心。因此你可以在应用程序外部来定义 bean,使用 Java 代码而不是 XML 文件。要使用这些新的特性,请参考@Configuration,@Bean,
@Import 和@DependsOn 注解
Spring 配置典型的是最少由一个容器必须管理的 bean 定义构成。基于 XML 的配置元数据展示了这些 bean 的配置是用在顶级`<beans/>`元素中的`<bean/>`元素完成的。
这些 bean 的定义对应构成应用程序中真实的对象。比如你定义的服务层的对象,数据访问对象(Data Access Object,DAO),表示对象比如 Struts 的 Action 实例,基础设置对象 比如 Hibernate 的 SesstionFactories,JMS 的 Queues 等这些典型的例子。而不用在容 器中定义细粒度的领域模型对象,因为这通常是由 DAO 和业务逻辑负责创建并加载的领域 对象。但是你也可以使用 Spring 和 AspectJ 整合来配置创建在 IoC 容器控制之外的对象。参 考使用在 Spring 中使用 AspectJ 来对领域对象进行依赖注入(8.8.1 节)。
下面的示例展示了基本的基于 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-3.0.xsd">
<bean id="..." class="...">
<!-- 这个bean的合作者和配置在这里编写 -->
</bean>
<bean id="..." class="...">
<!-- 这个bean的合作者和配置在这里编写 -->
</bean>
<!-- 更多的bean定义在这里编写 -->
</beans>
```
id 属性是一个字符串,用来标识定义的独立的 bean。class 属性定义了 bean 的类型, 需要使用类的完全限定名。id 属性的值指的就是协作对象。指写作对象的 XML 在这个示例 中没有展示;参考依赖(4.4 节)来获取更多信息。
### 4.2.2 实例化容器
实例化 Spring 的 IoC 容 器 是 很 简 单 的 。 定 位 路 径 或 所 有 路 径 提 供 给 ApplicationContext 的构造方法,实际上是表示资源的字符串,它就允许容器从各种外 部资源比如本地文件系统,Java 的 CLASSPATH 等来加载配置元数据
```
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml",
"daos.xml"});
```
> ![](https://box.kancloud.cn/2016-01-25_56a58526bb420.gif)
> 注意
> 在学习过 Spring 的 IoC 容器之后,你可能想更多了解 Spring 的 Resource 抽象,这在 第 5 章,资源中会描述,它提供了一个从定义 URI 语法的位置读取输入流的简便机制。特别 是,Resource 路径用来构建应用程序上下文,这会在 5.7 节“应用上下文和资源路径”中 来描述。
下面的示例展示了服务层代码(services.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-3.0.xsd">
<!-- services -->
<bean id="petStore"
class="org.springframework.samples.jpetstore.services
.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- 这个bean的其它合作者和配置在这里编写-->
</bean>
<!-- 更多的service bean的定义在这里编写 -->
</beans>
```
下面的示例展示了数据访问对象的 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-3.0.xsd">
<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.ibat is.SqlMapAccountDao">
<!-- 这个bean的其它合作者和配置在这里编写 -->
</bean>
<bean id="itemDao"
class="org.springframework.samples.jpetstore.dao.ibat is.SqlMapItemDao">
<!-- 这个bean的其它合作者和配置在这里编写 -->
</bean>
<!-- 更多数据访问对象的定义在这里编写 -->
</beans>
```
在上面的示例中,服务层代码由类 PetStoreServiceImpl 和两个基于 [iBatis](http://ibatis.apache.org/)(iBatis [现已更名为](http://www.mybatis.org/) [MyBatis](http://www.mybatis.org/),译者注)对象/实体映射框架的数据访问对象 SqlMapAccountDao 和 SqlMapItemDao 构成。property 的 name 元素指的是 JavaBean 的属性名,而 ref 元 素指的是其它 bean 定义的名称。id 和 ref 元素之间的这种联系表示了两个协作对象的依赖 关系。要了解更多配置对象依赖的信息,可以参考依赖(4.4 节)。
#### 4.2.2.1 处理基于 XML 的配置元数据
跨越多个 XML 文件中定义 bean 是很有用的。通常每个独立的 XML 配置文件代表了一 个逻辑层或架构中的一个模块。
你可以使用 ApplicationContext 的构造方法从所有的 XML 文件片段中来加载 bean。这个 构造方法可以接收多个 Resource 位置,这在之前的部分都已经看到了。另外,可以使用一个或多个`<import/>`元素来从另外的一个或多个文件中加载 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>
```
在 这 个示 例 中, 外部 的 bean 通 过 三个 文件 来 加载 ,分 别 是 services.xml , messageSource.xml 和 themeSource.xml。所有的位置路径都是相对于该引用文件的, 所以 service.xml 必须在和引用文件 相同路 径中 或 者 是 类 路 径 下 , 而 messageSource.xml 和 themeSource.xml 必 须 是 在 位 于 引 用 文 件 下 一 级 的 resources 路径下。正如你看到的,前部的斜杠被忽略了,这是由于路径都是相对的,最 好就不用斜线。文件的内容会被引入,包括顶级的`<beans/>`元素,根据 Spring 的 Schema 或 DTD,它必须是有效 bean 定义的 XML 文件。
> ![](https://box.kancloud.cn/2016-01-25_56a58526bb420.gif)
> 注意
> 在父目录中使用相对路径“../”来引用文件,这是可能的,但是不推荐这么做。这么做了会创建一个文件,它是当前应用程序之外的一个依赖。 特别是,这种引用对于“classpath:”的 URL(比如,“classpath:../service.xml”)是不推荐的,运行时的解析过 程会选择“最近的”类路径根目录并且会查看它的父目录。类路径配置的修改可能会导 致去选择一个不同的,不正确的目录。 你也可以使用资源位置的完全限定名来代替相对路径:比如,“file: C:/config /services.xml” 或“classpath:/config/services.xml”。这样的话,要注意你会耦合应用程序的配置到指定 的绝对路径。对于绝对路径,一般最好是保持一个间接的使用,比如通过占位符“${...}”, 这会基于运行时环境的 JVM 系统属性来解决。
### 4.2.3 使用容器
ApplicationContext 是能维护不同的 bean 和它们依赖注册的高级工厂接口。使用 `T getBean(Stringname, Class<T> requiredType)`方法你可以获取 bean 的实例。
ApplicationContext 允许你读取 bean 并且访问它们,如下所示:
```
// 创建并配置bean
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml",
"daos.xml"});
// 获取配置的实例
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
// 使用配置的实例
List userList service.getUsernameList();
```
使用 getBean()方法来获取 bean 的实例。ApplicationContext 接口有一些其它方法来获取 bean,但最好应用程序代码不使用它们。事实上,应用程序代码应该没有 getBean()方法的调用,那么就没有对 Spring API 的依赖了。比如,Spring 和 Web 框架整 合时,提供了对各种 Web 框架类库的依赖注入,不如控制器和 JSF 管理的 bean。
- 第一部分 Spring framework 概述
- 第 1 章 Spring Framework 介绍
- 1.1 依赖注入和控制反转
- 1.2 模块
- 1.3 使用方案
- 第二部分 Spring 3 的新特性
- 第 2 章 Spring 3.0 的新特性和增强
- 2.1 Java 5
- 2.2 改进的文档
- 2.3 新的文章和教程
- 2.4 新的模块组织方式和系统构建方式
- 2.5 新特性概述
- 第 3 章 Spring 3.1 的新特性和增强
- 3.1 新特性概述
- 第三部分 核心技术
- 第 4 章 IoC 容器
- 4.1 Spring IoC 容器和 bean 的介绍
- 4.2 容器概述
- 4.3 Bean 概述
- 4.4 依赖
- 4.5 Bean 的范围
- 4.6 自定义 bean 的性质
- 4.7 Bean 定义的继承
- 4.8 容器扩展点
- 4.9 基于注解的容器配置
- 4.10 类路径扫描和管理的组件
- 4.11 使用 JSR 330 标准注解
- 4.12 基于 Java 的容器配置