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的依赖。