对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

容器概述

org.springframework.context.ApplicationContext 接口表示 Spring IoC 容器,并负责实例化、配置和组装 bean。容器通过读取配置元数据来获取要实例化、配置和组装的对象的指令。配置元数据以 XML、Java 注解或 Java 代码形式表示。它允许你表达组成你的应用程序的对象以及这些对象之间的丰富依赖关系。spring-doc.cadn.net.cn

Spring提供了ApplicationContext接口的多个实现。 在独立应用程序中,通常会创建 ClassPathXmlApplicationContextFileSystemXmlApplicationContext 的实例。 虽然XML一直是定义配置元数据的传统格式,但您可以通过提供少量XML配置来声明性地启用对这些附加元数据格式的支持,从而指示容器使用Java注解或代码作为元数据格式。spring-doc.cadn.net.cn

在大多数应用程序场景中,不需要显式的用户代码来实例化一个或多个Spring IoC容器。例如,在Web应用程序场景中,应用程序的web.xml文件中的简单八行(或左右)的模板化Web描述符XML通常就足够了(参见Web应用程序的便捷ApplicationContext实例化)。如果您使用Eclipse的Spring工具(一个基于Eclipse的开发环境),可以通过几次鼠标单击或键盘输入轻松创建此模板化配置。spring-doc.cadn.net.cn

下面的图展示了Spring工作方式的概览。您的应用程序类与配置元数据结合在一起,这样,在ApplicationContext被创建和初始化之后,您将拥有一个完全配置并可执行的系统或应用程序。spring-doc.cadn.net.cn

container magic
图1. Spring IoC 容器

配置元数据

如上图所示,Spring IoC 容器使用一种配置元数据。这种配置元数据表示你作为应用程序开发人员,如何告诉 Spring 容器实例化、配置和组装你的应用程序中的对象。spring-doc.cadn.net.cn

配置元数据通常以一种简单且直观的XML格式提供,这就是本章大部分内容用来传达Spring IoC容器的关键概念和特性的格式。spring-doc.cadn.net.cn

基于 XML 的元数据不是唯一允许的配置元数据形式。 Spring IoC 容器本身与实际编写此配置元数据的格式完全解耦。如今,许多开发人员选择为他们的 Spring 应用程序使用 基于 Java 的配置

有关使用其他形式的元数据与Spring容器的信息,请参见:spring-doc.cadn.net.cn

Spring配置至少包含一个且通常包含多个由容器管理的bean定义。基于XML的配置元数据将这些bean配置为顶级<beans/>元素内的<bean/>元素。Java配置通常在@Configuration类中使用@Bean注解的方法。spring-doc.cadn.net.cn

这些bean定义对应于构成您应用程序的实际对象。 通常,您会定义服务层对象、持久层对象(如 仓库或数据访问对象(DAO),表示层对象(如Web控制器), 基础设施对象(如JPA EntityManagerFactory、JMS队列等)。 通常,不会在容器中配置细粒度的域对象,因为创建和加载域对象通常是仓库和业务逻辑的责任。spring-doc.cadn.net.cn

以下示例显示了基于 XML 的配置元数据的基本结构:spring-doc.cadn.net.cn

<?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
		https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="..." class="..."> (1) (2)
		<!-- 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>
1 id 属性是一个标识单个 bean 定义的字符串。
2 class 属性定义了 bean 的类型,并使用完全限定的类名。

id 属性的值可用于引用协作对象。引用协作对象的 XML 在此示例中未显示。有关更多信息,请参阅 依赖项spring-doc.cadn.net.cn

实例化容器

提供的用于ApplicationContext构造函数的路径或路径 是资源字符串,允许容器从各种外部资源加载配置元数据,例如本地文件系统、Java CLASSPATH等。spring-doc.cadn.net.cn

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")

在了解了Spring的IoC容器之后,您可能还想了解更多关于Spring的 Resource 抽象(如 资源 中所述) ,它提供了一种方便的机制,用于从URI语法定义的位置读取InputStream。特别是,Resource 路径用于构建应用程序上下文, 如 应用程序上下文和资源路径 中所述。spring-doc.cadn.net.cn

以下示例显示了服务层对象 (services.xml) 配置文件:spring-doc.cadn.net.cn

<?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
		https://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>

以下示例显示数据访问对象 daos.xml 文件:spring-doc.cadn.net.cn

<?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
		https://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>

在前面的示例中,服务层由 PetStoreServiceImpl 类和两个数据访问对象组成,其类型分别为 JpaAccountDaoJpaItemDao(基于 JPA 对象-关系映射标准)。property name 元素指的是 JavaBean 属性的名称,ref 元素指的是另一个 bean 定义的名称。idref 元素之间的这种关联表示了协作对象之间的依赖关系。有关配置对象依赖项的详细信息,请参阅 依赖项spring-doc.cadn.net.cn

基于 XML 的配置元数据的组合

将bean定义跨越多个XML文件可能会很有用。通常,每个单独的XML配置文件代表你架构中的一个逻辑层或模块。spring-doc.cadn.net.cn

您可以使用应用程序上下文构造函数从所有这些 XML 片段中加载 bean 定义。此构造函数接受多个 Resource 位置,如 上一节 所示。或者,使用一个或多个 <import/> 元素的出现来从另一个文件或文件中加载 bean 定义。下面的示例显示了如何操作:spring-doc.cadn.net.cn

<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.xmlthemeSource.xml。所有路径都是相对于执行导入的定义文件的,因此 services.xml 必须与执行导入的文件位于同一目录或类路径位置,而 messageSource.xmlthemeSource.xml 必须位于导入文件位置下的 resources 位置。如你所见,开头的斜杠会被忽略。然而,鉴于这些路径是相对的,最好完全不要使用斜杠。被导入文件的内容,包括顶层的 <beans/> 元素,必须根据 Spring Schema 是有效的 XML bean 定义。spring-doc.cadn.net.cn

使用相对 "../" 路径引用父目录中的文件是可能的,但不推荐。这样做会创建对当前应用程序外部文件的依赖。特别是,对于 classpath: URL(例如,classpath:../services.xml),运行时解析过程会选择“最近”的类路径根,然后查看其父目录。类路径配置的更改可能导致选择不同的、错误的目录。spring-doc.cadn.net.cn

您可以始终使用完全限定的资源位置而不是相对路径:例如,file:C:/config/services.xmlclasspath:/config/services.xml。但是,请注意,您正在将应用程序的配置与特定的绝对位置耦合。通常更 preferable 的是为这些绝对位置保持一个间接引用——例如,通过在运行时根据JVM系统属性解析的"${…​}"占位符。spring-doc.cadn.net.cn

命名空间本身提供了导入指令功能。Spring 提供的其他 XML 命名空间中还包含超出普通 bean 定义的进一步配置功能——例如,contextutil 命名空间。spring-doc.cadn.net.cn

Groovy Bean 定义 DSL

作为外部化配置元数据的另一个例子,bean定义也可以使用Spring的Groovy Bean Definition DSL来表达,这与Grails框架中的用法相同。通常,这样的配置位于一个".groovy"文件中,其结构如下面的例子所示:spring-doc.cadn.net.cn

beans {
	dataSource(BasicDataSource) {
		driverClassName = "org.hsqldb.jdbcDriver"
		url = "jdbc:hsqldb:mem:grailsDB"
		username = "sa"
		password = ""
		settings = [mynew:"setting"]
	}
	sessionFactory(SessionFactory) {
		dataSource = dataSource
	}
	myService(MyService) {
		nestedBean = { AnotherBean bean ->
			dataSource = dataSource
		}
	}
}

这种配置方式在很大程度上等同于XML bean定义,甚至支持Spring的XML配置命名空间。它还允许通过importBeans指令导入XML bean定义文件。spring-doc.cadn.net.cn

使用容器

ApplicationContext 是一个高级工厂接口,能够维护不同 bean 及其依赖项的注册表。通过使用方法 T getBean(String name, Class<T> requiredType),您可以获取您的 bean 实例。spring-doc.cadn.net.cn

ApplicationContext 允许你读取 bean 定义并访问它们,如下例所示:spring-doc.cadn.net.cn

// 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();
   import org.springframework.beans.factory.getBean

// create and configure beans
   val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")

   // retrieve configured instance
   val service = context.getBean<PetStoreService>("petStore")

   // use configured instance
   var userList = service.getUsernameList()

使用 Groovy 配置,引导过程看起来非常相似。它有一个不同的上下文实现类,该类了解 Groovy(但同时也理解 XML bean 定义)。以下示例显示了 Groovy 配置:spring-doc.cadn.net.cn

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy")

最灵活的变体是与reader委托结合使用的GenericApplicationContext,例如,对于XML文件使用XmlBeanDefinitionReader,如下例所示:spring-doc.cadn.net.cn

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();
val context = GenericApplicationContext()
XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml")
context.refresh()

您也可以在Groovy文件中使用 GroovyBeanDefinitionReader,如下例所示:spring-doc.cadn.net.cn

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();
val context = GenericApplicationContext()
GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy")
context.refresh()

您可以将这样的读者委托混合使用,在同一个 ApplicationContext 中,从不同的配置源中读取 bean 定义。spring-doc.cadn.net.cn

您可以使用 getBean 来获取您的 bean 实例。 ApplicationContext 接口还有一些其他方法用于获取 bean,但理想情况下,您的应用程序代码不应使用它们。实际上,您的应用程序代码不应该调用 getBean() 方法,因此完全不需要依赖 Spring API。例如,Spring 与 web 框架的集成为各种 web 框架组件(如控制器和 JSF 管理的 bean)提供了依赖注入,使您可以通过元数据(如自动装配注解)声明对特定 bean 的依赖。spring-doc.cadn.net.cn