核心技术-IOC-2

1.2.容器概述

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

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

在大多数应用程序场景中,不需要显式的用户代码来创建Spring IoC容器的一个或多个实例。例如,在web应用程序中,一个简单的8行(大约)样板web.xml文件通常就足够了(见Convenient ApplicationContext Instantiation for Web Applications)。如果您使用Spring Tools for Eclipse(一个强大的Eclipse开发环境),只需点击几下鼠标就可以轻松创建这个样板配置。

下图从较高层面展示了Spring是如何工作的。应用程序类与配置元数据相结合,这样在ApplicationContext创建并初始化之后,您就拥有了一个配置完整且可执行的应用程序。

Spring IoC容器

1.2.1.配置元数据

如上图所示,Spring IoC容器需要某种形式的配置元数据。此配置元数据代表了作为应用程序开发人员,您诉Spring容器如何实例化、配置和组装应用程序中的对象。

配置元数据传统上以一种简单而直观的XML格式提供,本章的大部分内容都使用这种格式来描述Spring IoC容器的关键概念和特性。

基于XML的元数据并不是唯一允许的配置元数据形式。Spring IoC容器本身与配置元数据的方式是完全解耦的。现在,许多开发人员为他们的Spring应用程序选择基于java的配置。

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

  • Annotation-based configuration:Spring2.5引入了对基于注释的配置元数据的支持。
  • Java-based configuration:从Spring 3.0开始,Spring JavaConfig项目提供的许多特性成为了核心Spring框架的一部分。Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. 因此,您可以通过使用Java而不是XML文件来定义应用程序类外部的bean。使用这些新特性,请参见@Configuration@Bean@Import@DependsOn注解。

Spring配置由至少一个(通常是多个)被容器管理的bean定义组成。基于XML的配置元数据通过root元素中的元素来配置。Java配置通常在@Configuration类中使用@Bean注解的方式来配置。

这些bean定义对应应用程序内的实际对象。比如:服务层对象(service)、数据访问层对象(DAO)、表示层对象(如Struts的Action,SpringMVC的Controller),还有一些底层基础设施对象(如Hibernate的SessionFactories、JMS的Queues)等等。通常,不需要在容器中配置细粒度的领域对象(POJO、JavaBean等),因为创建和加载领域对象通常是DAO和service的责任。但是,您可以使用Spring与AspectJ的集成来配置在IoC容器控制之外创建的对象。参见Using AspectJ to dependency-inject domain objects with Spring。

下面的例子展示了基于xml的配置元数据的基本结构:




    
        
    

    
        
    

    


  • id属性是标识单个bean定义的字符串。
  • class属性定义bean的类型并使用完全限定的类名。

id属性的值指向对象。本例中没有关于依赖项的配置示例。更多信息请参见Dependencies。

1.2.2.实例化一个容器

在下面示例代码中,提供给ApplicationContext构造函数的路径或路径列表是资源路径字符串,这些资源路径字符串允许容器从各种外部资源(如本地文件系统、Java CLASSPATH等)加载配置元数据。

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

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

以下示例显示了服务层对象(services.xml)配置文件:




    

    
        
        
        
    

    


下面的示例显示了数据访问对象(dao.xml)配置文件:




    
        
    

    
        
    

    


在上面的例子中,服务层由PetStoreServiceImpl类和JpaAccountDaoJpaItemDao类型的两个数据访问对象组成(基于JPA ORM)。namme元素指的是JavaBean属性的名称,而ref元素指的是另一个bean定义的名称。 idref元素之间的这种链接表示了对象之间的依赖关系。有关配置对象依赖关系的详细信息,请参见Dependencies。

组合基于XML的配置

将bean定义拆分成多个XML文件是很有用的。通常,每个单独的XML配置文件代表体系结构中的一个逻辑层或模块。

可以使用ApplicationContext构造函数从所有这些XML文件加载bean定义。这个构造函数接受多个Resource路径,如前一节所示。或者,使用元素从另一个或多个文件加载bean定义。下面的例子展示了如何做到这一点:


    
    
    

    
    

在上面的示例中,外部bean定义从三个文件加载:services.xmlmessageSource.xmlthemeSource.xml。所有导入文件路径都相对于执行导入的定义文件,因此services.xml必须与执行导入的文件位于相同的目录或类路径位置,而messageSource.xmlthemeSource.xml必须位于导入文件位置下面的resources目录里。如您所见,前面的斜杠被忽略了。但是,考虑到这些路径是相对的,最好不要使用斜杠。导入的文件的内容(包括顶级元素)必须是有效的基于Spring Schema的XML bean定义。

可以使用.. /来引用父目录中的文件,但不建议这样做。这样做将创建对当前应用程序之外的文件的依赖关系。特别是,不建议对classpath:类型的URL(例如,classpath:../services.xml)使用../,因为运行解析过程会选择最近的类路径根,然后查看其父目录。类路径的更改可能导致选择不同的、不正确的目录。

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

命名空间本身提供了导入指令功能。除了普通bean定义之外,Spring提供的XML名称空间中还提供了更多的配置特性——例如,contextutil名称空间。

1.2.3.使用容器

ApplicationContext是一个高级工厂的接口,该工厂维护了不同bean及其依赖项的注册表。通过使用T 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 userList = service.getUsernameList();

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

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

您可以在相同的ApplicationContext上混合使用不同的reader,以从不同的配置源读取bean定义。

然后可以使用getBean来获取bean的实例。ApplicationContext接口有一些其他的方法用于获取bean,但是,理想情况下,应用程序代码不应该使用它们。实际上,您的应用程序代码根本不应该调用getBean()方法,因此也根本不需要依赖于Spring的API。例如,Spring与web框架的集成为各种web框架组件(如controller和JSF bean)提供了依赖注入,允许您通过元数据(如自动装配注解)声明对特定bean的依赖。

你可能感兴趣的:(核心技术-IOC-2)