spring1.2

1.2. 容器概述

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

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

在大多数应用场景中,实例化 Spring IoC 容器的一个或多个实例不需要显式的用户代码。例如,在 Web 应用程序场景中,web.xml文件中简单的8行左右的关于描述 web 的样板通常就足够了(请参阅Convenient ApplicationContext Instantiation for Web Applications。如果使用Spring Tools for Eclipse(基于 Eclipse 的开发环境),那么仅需单击几次鼠标或击键即可轻松创建此样板配置。

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

图片.png

Figure 1. The Spring IoC container

1.2.1 配置元数据

如上图所示,Spring IoC 容器使用一种配置元数据的格式。此配置元数据表示您作为应用程序开发人员如何告诉 Spring 容器实例化,配置和组装应用程序中的对象。

传统方法是使用简单直观的 XML 格式配置元数据,这是本章大部分内容以此方法传达 Spring IoC 容器的关键概念和功能。

Note
基于 XML 的元数据不是配置元数据的唯一允许格式。 Spring IoC 容器本身与实际写入此配置元数据的格式是完全脱钩的。如今,许多开发人员为自己的 Spring 应用程序选择Java-based configuration

有关在 Spring 容器中使用其他形式的元数据的信息,请参见:

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

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

以下示例显示了基于 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示例中未显示有协作关系的其他对象 。有关更多信息,请参见Dependencies

1.2.2. 实例化容器

提供给ApplicationContext构造函数的 location path 或路径是resource strings,使容器从自各种外部资源加载配置元数据,例如本地文件系统,CLASSPATH等。

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

Note
了解了 Spring 的 IoC 容器之后,您可能想了解更多有关 Spring 的Resource抽象(如Resources中所述),该抽象为从 URI 语法中定义的 locations 读取 InputStream 提供了一种方便的机制。特别是,Resource路径用于构建应用程序上下文,如Application Contexts and Resource Paths中所述。

以下示例显示了服务层对象(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 definition 的名称。 idref元素之间的这种联系表达了协作对象之间的依赖性关系。有关配置对象的依赖项的详细信息,请参见Dependencies

构成基于 XML 的配置元数据

使 bean 定义跨越多个 XML 文件是很有用的。通常,每个单独的 XML 配置文件都代表架构中的逻辑层或模块。

您可以使用 application context 的构造函数从所有这些 XML 片段中加载 bean definition。该构造函数具有多个Resource位置,如previous section所示。或者,使用一个或多个<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>

在前面的示例中,从三个文件services.xml,messageSource.xml和themeSource.xml加载了外部 bean 定义。所有位置路径都相对于进行导入的定义文件,因此services.xml必须与进行导入的文件位于同一目录或 Classpath 位置,而messageSource.xml和themeSource.xml必须位于导入文件位置下方的resources位置。如您所见,斜杠被忽略。但是,鉴于这些路径是相对的,最好不要使用任何斜线。根据 Spring Schema,导入的文件的内容(包括顶级<beans/>元素)必须是有效的 XML bean 定义。

Note
可以但不建议使用相对的“ ../”路径引用父目录中的文件。这样做会创建对当前应用程序外部文件的依赖关系。特别是,不建议对classpath: URL(例如classpath:../services.xml)使用此引用,在 URL 中,运行时解析过程选择“最近”Classpath 根,然后查看其父目录。Classpath 配置的更改可能导致选择其他错误的目录。
您始终可以使用标准资源位置而不是相对路径:例如file:C:/config/services.xml或classpath:/config/services.xml。但是,请注意,您正在将应用程序的配置耦合到特定的绝对位置。通常,最好为这样的绝对位置保留一个间接寻址,例如通过在运行时针对 JVM 系统属性解析的“ ${…}”占位符。

名称空间本身提供了导入指令功能。 Spring 提供的一系列 XML 名称空间(例如context和util名称空间)中提供了超出普通 bean 定义的其他配置功能。

The Groovy Bean Definition DSL

1.2.3. 使用容器

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与 读取器 结合使用,例如,对于 XML 文件,是XmlBeanDefinitionReader,如以下示例所示:

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上混合并匹配此类阅读器委托,从不同的配置源读取 Bean 定义。

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容