Spring IoC容器概述

https://docs.spring.io/spring-framework/reference/core/beans/basics.html

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

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

在大多数应用场景中,不需要显式的用户代码来实例化一个或多个 Spring IoC 容器的实例。例如,在 web 应用场景中,通常只需在应用程序的 web.xml 文件中提供简单的八行(左右)样板 web 描述符 XML 就足够了。如果你使用 Spring Tools for Eclipse(一种基于 Eclipse 的开发环境),可以通过几次鼠标点击或按键轻松创建这些样板配置。

下图展示了 Spring 的高级视图。你的应用程序类与配置元数据结合,以便在创建和初始化 ApplicationContext 之后,你将拥有一个完全配置且可执行的系统或应用程序。
在这里插入图片描述

配置元数据

如前图所示,Spring IoC 容器使用一种配置元数据。这种配置元数据代表你作为应用程序开发者如何告诉 Spring 容器实例化、配置和组装应用程序中的对象。

配置元数据通常以简单直观的 XML 格式提供,这也是本章大部分内容用来传达 Spring IoC 容器的关键概念和特性的方式。

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

Spring 配置至少包含一个,通常多于一个容器必须管理的 bean 定义。基于 XML 的配置元数据将这些 bean 配置为顶级 <beans/> 元素内的 <bean/> 元素。Java 配置通常在 @Configuration 类中使用带有 @Bean 注解的方法。

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

以下示例显示了基于 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
		https://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 属性是一个字符串,用于标识单个 bean 定义。
  • class 属性定义了 bean 的类型,并使用完全限定的类名。

id 属性的值可以用来引用协作对象。本示例中未显示引用协作对象的 XML。

实例化容器

提供给 ApplicationContext 构造函数的位置路径是一个或多个资源字符串,它们让容器能够从各种外部资源加载配置元数据,例如本地文件系统、Java CLASSPATH 等。

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

Spring 的资源抽象(如Resources中所述),它提供了一种方便的机制,用于从 URI 语法定义的位置读取 InputStream。特别是,资源路径被用来构造应用程序上下文,如应用程序上下文和资源路径中所述。

以下示例显示了服务层对象(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
		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 文件:

<?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 元素之间的这种链接表达了协作对象之间的依赖关系。

编写基于 XML 的配置元数据

让 bean 定义跨越多个 XML 文件可能会很有用。通常,每个单独的 XML 配置文件代表体系结构中的一个逻辑层或模块。

你可以使用应用程序上下文构造函数从所有这些 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.xmlmessageSource.xmlthemeSource.xml。所有位置路径都是相对于执行导入操作的定义文件的,所以 services.xml 必须与执行导入的文件位于同一目录或类路径位置,而 messageSource.xmlthemeSource.xml 必须位于导入文件下方的资源位置。如你所见,前导斜杠会被忽略。然而,鉴于这些路径是相对的,最好不要使用斜杠。被导入的文件内容,包括顶级 <beans/> 元素,必须是有效的 XML bean 定义,符合 Spring Schema。

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

你总是可以使用完全限定的资源位置而不是相对路径:例如,file:C:/config/services.xmlclasspath:/config/services.xml。但是,请注意,这样做会将应用程序的配置与特定的绝对位置耦合。通常更可取的是保持对这些绝对位置的间接引用——例如,通过在运行时针对 JVM 系统属性解析的 “${…​}” 占位符。

命名空间本身提供了导入指令功能。除了简单的 bean 定义之外,Spring 提供的一组 XML 命名空间还提供了更多的配置功能——例如,contextutil 命名空间。

Groovy Bean 定义领域特定语言(DSL)

作为外部化配置元数据的进一步示例,bean 定义也可以使用 Spring 的 Groovy Bean Definition DSL 来表示,就像 Grails 框架中所使用的那样。通常,这样的配置位于具有以下示例所示结构的 “.groovy” 文件中:

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 定义文件。

使用容器

ApplicationContext 是一个高级工厂的接口,能够维护不同 bean 及其依赖关系的注册表。通过使用 getBean(String name, Class requiredType) 方法,可以检索你的 bean 的实例。

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();

使用 Groovy 配置时,引导过程看起来非常相似。它有一个不同的上下文实现类,这个类能够识别 Groovy(但也理解 XML bean 定义)。以下示例展示了 Groovy 配置:

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

最灵活的变体是 GenericApplicationContext,它与 reader delegates 结合使用——例如,与 XmlBeanDefinitionReader 一起用于 XML 文件,如下例所示:

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

也可以使用 GroovyBeanDefinitionReader 用于 Groovy 文件,如下例所示:

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

可以在同一个 ApplicationContext 上混合使用这些 reader delegates,从不同的配置源读取 bean 定义。

然后,可以使用 getBean 来检索你的 bean 实例。ApplicationContext 接口还有一些其它用于检索 bean 的方法,但理想情况下,你的应用程序代码应永远不使用它们。实际上,你的应用程序代码根本不应该调用 getBean() 方法,因此完全不依赖于 Spring API。例如,Spring 与 Web 框架的集成为各种 Web 框架组件(如控制器和 JSF-managed beans)提供了依赖注入,让你可以通过元数据(如自动装配注解)声明对特定 bean 的依赖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值