Spring-Framework-参考文档容器概述

5次阅读

共计 6772 个字符,预计需要花费 17 分钟才能阅读完成。

容器概述

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

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

在大多数应用程序场景中,不需要显式用户代码来实例化 Spring IoC 容器的一个或多个实例。例如,在 web 应用程序场景中,在应用程序的 web.xml 文件中使用 8 行左右的简单样例 web 描述符 XML 就足够了(请参阅方便的 web 应用程序的 ApplicationContext 实例化)。如果使用 Spring Tool Suite(一个 Eclipse 支持的开发环境),只需单击几下鼠标或按键,就可以轻松创建这个样板配置。

下图显示了 Spring 如何工作的高级别视图,你的应用程序类与配置元数据相结合,这样,在创建并初始化 ApplicationContext 之后,你就拥有了一个完全配置的可执行系统或应用程序。

配置元数据

如上图所示,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 定义,并且通常包含多个 bean 定义,基于 XML 的配置元数据将这些 bean 配置为顶级 <beans/> 元素中的 <bean/> 元素,Java 配置通常在 @Configuration 类中使用 @Bean 注解的方法。

这些 bean 定义对应于组成应用程序的实际对象,通常,你定义服务层对象、数据访问对象(DAO)、表示对象(如 Struts Action实例)、基础设施对象(如 Hibernate SessionFactories)、JMS Queues等等。通常,不会在容器中配置细粒度域对象,因为通常由 DAO 和业务逻辑负责创建和加载域对象。不过,你可以使用 Spring 与 AspectJ 的集成来配置在 IoC 容器控制之外创建的对象。

下面的例子展示了基于 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 的 IoC 容器之后,你可能想了解更多关于 Spring 的 Resource 抽象的信息,它提供了一种方便的机制,可以从 URI 语法中定义的位置读取 InputStream,特别是,Resource 路径用于构造应用程序上下文。

下面的示例显示了服务层对象(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必须位于导入文件位置下方的 resources 位置。可以看到,前面的斜杠被忽略了,但是,由于这些路径是相对的,所以最好不要使用斜杠,根据 Spring Schema,导入的文件的内容,包括顶层<beans/> 元素,必须是有效的 XML bean 定义。

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

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

名称空间本身提供导入指令特性,除了普通 bean 定义之外,Spring 提供的 XML 名称空间的选择还提供了其他配置特性 — 例如 contextutil名称空间。

Groovy Bean Definition 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 及其依赖项的注册表,通过使用方法T getBean(String name, Class<T> 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 委托相结合 — 例如,使用 XmlBeanDefinitionReader 来处理 XML 文件,如下例所示:

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

你还可以对 Groovy 文件使用GroovyBeanDefinitionReader,如下面的示例所示:

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

你可以在相同的 ApplicationContext 上混合和匹配这样的 reader 委托,从不同的配置源读取 bean 定义。

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


上一篇:Spring IoC 容器和 bean 介绍

正文完
 0