容器概述

org.springframework.context.ApplicationContextinterface 表示 Spring IoC 容器,并负责实例化、配置和组装 bean。 容器在组件上获取其指令,以实例化、配置和 通过读取配置元数据进行汇编。可以表示配置元数据 作为带注释的组件类、具有工厂方法的配置类或外部 XML 文件或 Groovy 脚本。无论使用哪种格式,您都可以编写应用程序,并将 这些组件之间丰富的相互依赖关系。spring-doc.cadn.net.cn

ApplicationContext接口是核心 Spring 的一部分。 在独立应用程序中,通常会创建一个AnnotationConfigApplicationContextClassPathXmlApplicationContext.spring-doc.cadn.net.cn

在大多数应用程序场景中,不需要显式用户代码来实例化一个或 Spring IoC 容器的更多实例。例如,在普通 Web 应用程序场景中, 一个简单的样板 Web 描述符 XML。web.xml应用程序的文件就足够了(参见 Web 应用程序的便捷 ApplicationContext 实例化)。 在 Spring Boot 场景中,应用程序上下文是隐式引导的 基于通用设置约定。spring-doc.cadn.net.cn

下图显示了 Spring 工作原理的高级视图。您的应用程序类 与配置元数据结合使用,以便在ApplicationContext是 创建并初始化后,您将拥有一个完全配置且可执行的系统或应用程序。spring-doc.cadn.net.cn

容器魔术
图 1.Spring IoC 容器

配置元数据

如上图所示, Spring IoC 容器使用一种形式的 配置元数据。此配置元数据表示您作为 application developer,告诉 Spring 容器实例化、配置、 并在应用程序中组装组件。spring-doc.cadn.net.cn

Spring IoC 容器本身与此格式完全解耦 配置元数据实际上是写入的。如今,许多开发人员为他们的 Spring 应用程序选择基于 Java 的配置spring-doc.cadn.net.cn

Spring 配置由至少一个(通常多个)bean 定义组成 容器必须管理。Java 配置通常使用@Bean-注释 方法中的@Configuration类,每个类对应一个 bean 定义。spring-doc.cadn.net.cn

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

XML 作为外部配置 DSL

基于 XML 的配置元数据将这些 bean 配置为<bean/>元素 顶级<beans/>元素。以下示例显示了 基于 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 idattribute 是标识各个 bean 定义的字符串。
2 classattribute 定义 bean 的类型,并使用完全限定的 类名。

idattribute 可用于引用协作对象。The XML 本例中未显示 for reference to collaborative objects。有关更多信息,请参阅依赖项spring-doc.cadn.net.cn

对于实例化容器,XML 资源文件的位置路径或 paths 需要提供给ClassPathXmlApplicationContext构造函数,让 容器加载来自各种外部资源的配置元数据,例如 作为本地文件系统,JavaCLASSPATH等。spring-doc.cadn.net.cn

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

在了解 Spring 的 IoC 容器之后,您可能希望了解有关 Spring 的Resourceabstraction (如 参考资料 中所述) 它提供了一种方便的机制,用于从定义的位置读取 InputStream 在 URI 语法中。特别Resourcepaths 用于构建应用程序上下文, 如应用程序上下文和资源路径中所述。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 Object-Relational Mapping 标准上)。这property name元素引用 name,以及ref元素引用另一个 bean 的名称 定义。这种idref元素表示 协作对象。有关配置对象依赖项的详细信息,请参阅依赖项spring-doc.cadn.net.cn

编写基于 XML 的配置元数据

让 Bean 定义跨多个 XML 文件可能很有用。通常,每个个体 XML 配置文件表示体系结构中的逻辑层或模块。spring-doc.cadn.net.cn

您可以使用ClassPathXmlApplicationContext构造函数来加载 bean 定义 XML 片段。此构造函数采用多个Resourcelocations 的 LOCATIONS 中,如上一节所示。或者 使用<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必须在 与执行导入的文件相同的目录或 Classpath 位置,而messageSource.xmlthemeSource.xml必须位于resources位置位于 导入文件的位置。如您所见,前导斜杠将被忽略。然而,鉴于 这些路径是相对的,最好根本不使用斜杠。这 正在导入的文件的内容,包括 Top Level<beans/>元素,必须 根据 Spring Schema 是有效的 XML bean 定义。spring-doc.cadn.net.cn

可以使用 相对 “../“ 路径。这样做会创建对当前 应用。具体而言,不建议将此引用用于classpath:URL(对于 例classpath:../services.xml),其中运行时解析进程选择 “nearest” classpath 根目录,然后查看其父目录。类路径 配置更改可能会导致选择不同的错误目录。spring-doc.cadn.net.cn

您始终可以使用完全限定的资源位置而不是相对路径:对于 例file:C:/config/services.xmlclasspath:/config/services.xml.但是,be 知道您正在将应用程序的配置耦合到特定的 absolute 地点。通常最好为这种绝对的 locations — 例如,通过针对 JVM 解析的 “${...}” 占位符 系统属性。spring-doc.cadn.net.cn

命名空间本身提供了 import 指令功能。进一步 除了普通 Bean 定义之外的配置功能在 SELECTION 中可用 的 XML 命名空间中 — 例如,contextutil命名空间。spring-doc.cadn.net.cn

Groovy Bean 定义 DSL

作为外部化配置元数据的另一个示例,bean 定义还可以 用 Spring 的 Groovy Bean 定义 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 配置命名空间。它还允许导入 XML Bean 定义文件通过importBeans命令。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()

With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). The following example shows Groovy configuration:spring-doc.cadn.net.cn

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

The most flexible variant is GenericApplicationContext in combination with reader delegates — for example, with XmlBeanDefinitionReader for XML files, as the following example shows: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()

You can also use the GroovyBeanDefinitionReader for Groovy files, as the following example shows: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()

You can mix and match such reader delegates on the same ApplicationContext, reading bean definitions from diverse configuration sources.spring-doc.cadn.net.cn

You can then use getBean to retrieve instances of your beans. The ApplicationContext interface has a few other methods for retrieving beans, but, ideally, your application code should never use them. Indeed, your application code should have no calls to the getBean() method at all and thus have no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides dependency injection for various web framework components such as controllers and JSF-managed beans, letting you declare a dependency on a specific bean through metadata (such as an autowiring annotation).spring-doc.cadn.net.cn