1.2. 容器概述
最后更新于
最后更新于
org.springframework.context.ApplicationContext
接口代表 Spring IoC 容器,负责实例化、配置和组装 bean。容器通过读取配置元数据来获取关于要实例化、配置和组装哪些对象的指令。配置元数据以 XML、Java 注解或 Java 代码表示。它允许您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。
Spring 提供了ApplicationContext
接口的几个实现。在独立应用程序中,通常会创建 ClassPathXmlApplicationContext
或FileSystemXmlApplicationContext
的实例。虽然 XML 一直是定义配置元数据的传统格式,但您可以通过提供少量 XML 配置来以声明方式支持这些附加元数据格式,从而指示容器使用 Java 注解或代码作为元数据格式。
在大多数应用场景中,不需要显式用户代码来实例化 Spring IoC 容器的一个或多个实例。例如,在 Web 应用程序场景中,应用程序web.xml
文件中简单的八(大约)行样板 Web 描述符 XML 通常就足够了(请参阅Web 应用程序的便捷 ApplicationContext 实例化)。如果您使用 Spring Tools for Eclipse(一个 Eclipse 驱动的开发环境),您可以通过几次鼠标单击或击键轻松创建此样板配置。
下图显示了 Spring 如何工作的高级视图。您的应用程序类与配置元数据相结合,以便在ApplicationContext
创建和初始化之后,您拥有一个完全配置且可执行的系统或应用程序。
图 1. Spring IoC 容器
1.2.1. 配置元数据
如上图所示,Spring IoC 容器使用一种形式的配置元数据。此配置元数据表示您作为应用程序开发人员如何告诉 Spring 容器实例化、配置和组装应用程序中的对象。
配置元数据传统上以简单直观的 XML 格式提供,本章大部分内容都使用这种格式来传达 Spring IoC 容器的关键概念和特性。
基于 XML 的元数据不是唯一允许的配置元数据形式。Spring IoC 容器本身与实际编写此配置元数据的格式完全分离。如今,许多开发人员 为其 Spring 应用程序 选择基于 Java 的配置。
有关在 Spring 容器中使用其他形式的元数据的信息,请参阅:
基于注解的配置:Spring 2.5 引入了对基于注解的配置元数据的支持。
基于 Java 的配置:从 Spring 3.0 开始,Spring JavaConfig 项目提供的许多特性成为核心 Spring Framework 的一部分。因此,您可以使用 Java 而不是 XML 文件来定义应用程序类外部的 bean。要使用这些新功能,请参阅 @Configuration
、 @Bean
、 @Import
和@DependsOn
注解。
Spring 配置包含容器必须管理的至少一个,通常是多个 bean 定义。基于 XML 的配置元数据将这些 bean 配置为<bean/>
顶级元素内的<beans/>
元素。Java 配置通常在@Configuration
类中使用@Bean
注解的方法。
这些 bean 定义对应于构成应用程序的实际对象。通常,您定义服务层对象、数据访问对象 (DAO)、表示对象(如 StrutsAction
实例)、基础设施对象(如 Hibernate SessionFactories
、JMSQueues
等)。通常,不会在容器中配置细粒度的域对象,因为创建和加载域对象通常是 DAO 和业务逻辑的责任。但是,您可以使用 Spring 与 AspectJ 的集成来配置在 IoC 容器控制之外创建的对象。请参阅Using AspectJ to dependency-inject domain objects with Spring。
以下示例显示了基于 XML 的配置元数据的基本结构:
id
属性是标识单个 bean 定义的字符串。
class
属性定义 bean 的类型并使用完全限定的类名。
id
属性的值是指协作对象。此示例中未显示用于引用协作对象的 XML。有关更多信息,请参阅 依赖项。
1.2.2. 实例化一个容器
提供给ApplicationContext
构造函数的一个或多个位置路径是资源字符串,允许容器从各种外部资源(例如本地文件系统、Java CLASSPATH
等)加载配置元数据。
在了解了 Spring 的 IoC 容器之后,您可能想了解更多关于 Spring 的 Resource
抽象(如参考资料中所述),它提供了一种方便的机制来从 URI 语法中定义的位置读取 InputStream。特别是, Resource
路径用于构造应用程序上下文,如应用程序上下文和资源路径中所述。
以下示例显示了服务层对象(services.xml)
配置文件:
以下示例显示了数据访问对象daos.xml
文件:
在前面的示例中,服务层由PetStoreServiceImpl
类和两个类型的数据访问对象JpaAccountDao
和JpaItemDao
(基于 JPA 对象-关系映射标准)组成。property name
元素引用JavaBean 属性的名称,元素ref
引用另一个bean 定义的名称。元素id
之间的这种ref
联系表达了协作对象之间的依赖关系。有关配置对象依赖项的详细信息,请参阅 依赖项。
编写基于 XML 的配置元数据
让 bean 定义跨越多个 XML 文件会很有用。通常,每个单独的 XML 配置文件都代表架构中的一个逻辑层或模块。
您可以使用应用程序上下文构造函数从所有这些 XML 片段加载 bean 定义。此构造函数采用多个Resource
位置,如上 一节所示。或者,使用<import/>
元素的一个或多个实例从另一个文件或多个文件加载 bean 定义。以下示例显示了如何执行此操作:
在前面的示例中,外部 bean 定义是从三个文件加载的: services.xml
、messageSource.xml
和themeSource.xml
. 所有位置路径都相对于执行导入的定义文件,因此services.xml
必须与执行导入的文件位于同一目录或类路径位置,而 messageSource.xml
和themeSource.xml
必须位于导入文件位置下方的resources
位置。如您所见,前导斜杠被忽略。但是,鉴于这些路径是相对的,最好不要使用斜线。根据 Spring Schema ,被导入文件的内容,包括顶级<beans/>
元素,必须是有效的 XML bean 定义。
可以但不推荐使用相对“../”路径来引用父目录中的文件。这样做会创建对当前应用程序之外的文件的依赖。特别是,不建议将此引用用于
classpath:
URL(例如,classpath:../services.xml
),其中运行时解析过程选择“最近的”类路径根,然后查看其父目录。类路径配置更改可能会导致选择不同的、不正确的目录。您始终可以使用完全限定的资源位置而不是相对路径:例如,file:C:/config/services.xml
或classpath:/config/services.xml
. 但是,请注意您将应用程序的配置耦合到特定的绝对位置。通常最好为此类绝对位置保留间接性——例如,通过在运行时针对 JVM 系统属性解析的“${...}”占位符。
命名空间本身提供了导入指令功能。除了普通的 bean 定义之外,更多的配置特性可以在 Spring 提供的 XML 命名空间的选择中使用——例如,context
和util
命名空间。
Groovy Bean 定义 DSL
作为外部化配置元数据的另一个示例,bean 定义也可以在 Spring 的 Groovy Bean 定义 DSL 中表示,如 Grails 框架中已知的那样。通常,此类配置位于“.groovy”文件中,其结构如下例所示:
这种配置风格在很大程度上等同于 XML bean 定义,甚至支持 Spring 的 XML 配置命名空间。它还允许通过importBeans
指令导入 XML bean 定义文件。
1.2.3. 使用容器
ApplicationContext
是一个高级工厂的接口,能够维护不同 bean 及其依赖项的注册表。通过使用方法T getBean(String name, Class<T> requiredType)
,您可以检索 bean 的实例。
ApplicationContext
允许您读取 bean 定义并访问它们,如以下示例所示:
使用 Groovy 配置,引导看起来非常相似。它有一个不同的上下文实现类,它支持 Groovy(但也理解 XML bean 定义)。以下示例显示了 Groovy 配置:
最灵活的变体是GenericApplicationContext
与阅读器委托结合使用——例如,XmlBeanDefinitionReader
与XML 文件结合使用,如以下示例所示:
您还可以对Groovy 文件使用GroovyBeanDefinitionReader
,如以下示例所示:
您可以在同一个ApplicationContext
上混合和匹配此类读取器委托,从不同的配置源读取 bean 定义。
然后,您可以使用getBean
来检索 bean 的实例。ApplicationContext
接口还有一些其他检索 bean 的方法,但理想情况下,您的应用程序代码不应该使用它们。实际上,您的应用程序代码根本不应该调用 getBean()
方法,因此根本不依赖 Spring API。例如,Spring 与 Web 框架的集成为各种 Web 框架组件(例如控制器和 JSF 管理的 bean)提供了依赖注入,让您可以通过元数据(例如自动装配注解)声明对特定 bean 的依赖。