1.2.1.配置元数据

如上图所示,Spring IOC容器使用一种形式的配置元数据来表示如何通知Spring容器实例化、配置和组装应用程序中的对象。

配置元数据传统上是以简单直观的XML格式提供的,这是本章的大部分内容用来XML(这是为理解方便,实际项目中,可能用注解方式)。

基于XML的元数据不是唯一允许的配置元数据形式。Spring IOC容器本身与实际编写此配置元数据的格式完全分离。如今,许多开发人员选择基于Java代码的配置来实现Spring应用程序。

另外其他形式的元数据,请参见:

  • 基于注释的配置:Spring2.5引入了对基于注释的配置元数据的支持
  • 基于Java代码的配置:从Spring 3开始,Spring JavaConfig项目提供的许多特性成为核心Spring框架的一部分。因此,可以使用Java来定义应用程序类外部的bean。要使用这些新功能,请参见@Configuration, @Bean, @Import和@DependsOn。

Spring配置由至少一个bean定义组成。XML文件将这些bean配置在顶级<beans/>元素中的<bean/>元素。对于的,Java配置通常在@Configuration中使用@Bean注释。

这些bean定义对应于组成应用程序的实际对象。通常,您需要定义服务层对象、数据访问对象(DAO)、表示对象(如Struts操作实例)、基础结构对象(如Hibernate会话行为)、JMS队列对象等。通常,我们不会在容器中配置细粒度的域对象,因为DAOS和业务逻辑通常负责创建和加载域对象。但是,您可以使用Spring与AspectJ的集成来配置在IOC容器控制之外创建的对象。请参见使用AspectJ来依赖项使用Spring注入域对象。

下面的示例显示了基于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="...">   
        <!-- 此bean的相关者和配置在这里配置 -->
    </bean>

    <bean id="..." class="...">
        <!-- 此bean的相关者和配置在这里配置 -->
    </bean>

    <!-- 在这里定义更多的bean-->

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

1.2.2.实例化容器

ApplicationContext加载配置元数据的方法如下:

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

以下示例显示了服务层对象(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"/>
        <!-- 此bean的其他相关者和配置请此处配置-->
    </bean>

    <!-- 更多服务的bean定义 -->

</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">
        <!-- 此bean的其他相关者和配置请此处配置 -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- 此bean的其他相关者和配置请此处配置 -->
    </bean>

    <!-- 更多数据访问对象的bean定义-->

</beans>

在前面的示例中,服务层由PetStoreServiceImpl类和两个类型为JpaAccountDao和JpaItemDao(基于jpa对象关系映射标准)的数据访问对象组成。属性元素名引用JavaBean属性的名称,ref元素引用另一个bean定义的名称。id和ref元素之间的链接表示协作对象之间的依赖关系。有关配置对象依赖项的详细信息,请参阅依赖项。

XML配置元数据的组成
可以让bean定义跨越多个XML文件。通常,每个单独的XML配置文件表示体系结构中的逻辑层或模块。
您可以使用 ApplicationContext函数从所有这些XML文件中加载bean定义。如前一节所示,这个构造函数采用多个资源位置。或者,使用一个或多个<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.xml、messageSource.xml和themeSource.xml。services.xml必须与执行导入的文件位于同一目录或类路径位置,而messageSource.xml和themeSource.xml在子目录中。如您所见,前导斜杠被忽略。根据Spring Schema,要导入的文件的内容(包括顶层的<beans/>元素)必须是有效的XML bean定义。
命名空间本身提供了导入指令功能。在Spring提供的一系列XML名称空间中,除了纯bean定义之外,还提供了其他配置功能,例如Context和Util名称空间。

Groovy 的bean定义
作为外部化配置元数据的另一个例子,Bean定义也可以用Spring的Groovy bean定义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定义文件。

1.2.3. 使用容器

ApplicationContext是高级工厂的接口,它能够维护不同bean及其依赖项的注册表。通过使用方法 T getBean(String name, Class<T> requiredType),您可以检索bean的实例。
ApplicationContext允许您读取bean定义并访问它们,如下例所示:

// 创建和配置beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// 检索配置的实例
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// 使用配置实例
List<String> userList = service.getUsernameList();

对于groovy配置,引导看起来非常相似。它有一个不同的上下文实现类,它支持groovy(但也理解XML bean定义)。下面的示例显示了groovy配置:

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

最灵活的是GenericApplicationContext,与一个reader委托结合使用-例如,使用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();

您可以在同一应用程序上下文上混合和匹配这样的reader委托,从不同的配置源读取bean定义。

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