一、容器概览
1、元数据的配置
元数据的配置,一般来说可以分为三种方式:最简单直接的就是使用xml配置文件,另外两个就是spring注解配置与使用java注解的配置。这次我们先从xml开始谈起,逐步进行深入。
在xml里,使用<bean>和</bean>来定义一个元数据。一般来说,你可以定义service层的对象,data access 对象,表示层对象(如 Structs Action)等等。如下,给出了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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="..."> <!-- 配置bean的依赖对象与属性设置--> </bean> <bean id="..." class="..."> <!-- .... --> </bean> </beans>
2、初始换一个容器
在spring里,最经典的容器就是ApplicationContext,其初始化如下:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
当中service.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 http://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> <!-- 配置更多的service 对象 --> </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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao"> <!-- 其他依赖对象和基础配置--> </bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao"> <!-- ... --> </bean> <!-- 配置更多的data access 对象--> </beans>
在上面的Demo里,服务层对象是PetStoreServiceImpl类对象,两个data access对象分别是SqlMapAccountDao和SqlMapItemDao类对象,这两个data access对象都是基于iBatics ORM框架的。
如果有多个xml元数据的配置文件,可以将他们组合成一个基于xml的配置文件,如下:
<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,其中services.xml必须在classpath路径下,而messageSource.xml和themeSource.xml则需要在resources文件夹下。
3.使用容器
所有配置的最终目的都是为了使用,现在来看一下如何使用容器ApplicationContext。ApplicationContext在维护一个各个Bean和其依赖项的注册表。使用方法T getBean(String name,Class<T> requiredType>,可以获得对应Bean的实例。如下:
// 创建容器 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); // 获取配置Bean的实例 PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class); // 使用实例 List userList = service.getUsernameList();
二、Bean的概览
ioc容器管理着一个或多个bean。这些bean都可以通过指定的配置方式,提供给ioc容器。如上文谈到的xml的配置方式<bean/>
相对于容器本身来说,这些bean都会作为 BeanDefinition 的对象,一般包含了以下元数据:
- 全限定名(包+类名):java bean 类名
- bean的行为:指定了bean在容器里的行为,包括作用域 scope,生命周期的回调方法等等
- bean的依赖对象
- 其他属性配置:如连接池的连接数量
如下,是一些常用的bean属性:class,name,scope,constructor arguments,properties,autowiring mode,lazy-initialization mode,initialization method,destruction method。
1、命名Bean
在xml配置文件里,可以使用属性 id 或 name 来命名一个bean。当中 id 是bean的唯一标志名,在整个 xml 文档中唯一。属性 name 用来为 id 指定一个或多个别名,多个别名之间用逗号”,“,分号”;“或者空格来分开。
当你没有为bean 指定 id 或 name 时,容器会自动为此bean 指定一个唯一的标志名。当然了,如果你需要 ref 指向此 bean ,就必须为其指定一个name
2、bean 的别名
<alias name="fromName" alias="toName"/>
3、实例化 bean
spring 提供了三种方式实例化一个 bean。基于xml配置的,可以使用类构造器,静态工厂方法,实例工厂方法
- 使用类构造器实例化bean,如下:
<bean id="exampleBean" class="examples.ExampleBean"/> <bean name="anotherExample" class="examples.ExampleBeanTwo"/>
- 使用静态工厂方法
静态工厂方法要求类需要包含一个静态工厂方法, 同时需要再xml配置文件里指定工厂方法,如下:(createInstance 必须是static方法)
<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>
ClientService类设计如下:
public class ClientService { private static ClientService clientService = new ClientService(); private ClientService() {} public static ClientService createInstance() { return clientService; } }
- 实例工厂方法
与静态工厂方法类似,实例化工厂方法是使用容器里已存在 factory bean 的非静态方法来实例化一个新bean。使用这种方式实例化bean,应该将属性 name 设置为空,设置 factory-bean指定factoryBean,属性 factory-method指定实例化方法,如下:
<!-- factoryBean,包含一个非静态方法 createInstance() --> <bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- 注入其他依赖对象 --> </bean> <!-- 通过factoryBean 实例化的 bean --> <bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>
DefaultServiceLocator设计如下:
public class DefaultServiceLocator { private static ClientService clientService = new ClientServiceImpl(); private DefaultServiceLocator() {} public ClientService createClientServiceInstance() { return clientService; } }
深入一点谈就是,一个factory bean可以有多个工厂方法,如下:
<bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- 注入其他依赖对象--> </bean> <bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/> <bean id="accountService" factory-bean="serviceLocator" factory-method="createAccountServiceInstance"/>
DefaultServiceLocator设计如下:
public class DefaultServiceLocator { private static ClientService clientService = new ClientServiceImpl(); private static AccountService accountService = new AccountServiceImpl(); private DefaultServiceLocator() {} public ClientService createClientServiceInstance() { return clientService; } public AccountService createAccountServiceInstance() { return accountService; } }