Technorati 标记: spring, java

一、容器概览

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;
  }
}