springframwork入门之一 IOC

在spring里,IOC(反转控制)通常伴随着DI(依赖注入)出现,IOC是一种思想,DI是它的一种实现手段


  • 几个重要的包和类
    容器
    容器
    Bean

    几个重要的包和类

    基础包:
  • org.springframework.beans
  • org.springframework.context

基础接口:

  • BeanFactory
  • ApplicationContext
    BeanFactory和ApplicationContext的继承关系

其中Application增加如下特性:

  1. 更好的与springAOP模块集成
  2. Message resource 处理(国际化部分)
  3. 事件的发布
  4. 应用层特定的上下文,例如Web应用程序中使用的WebApplicationContext。

简而言之,BeanFactory提供了配置框架和基本功能,而ApplicationContext是BeanFactory的完整超集,在本文介绍IOC时都统一使用ApplicationContext来作为IOC容器。

容器

器通过读取配置元数据来获取有关要实例化,配置和组装哪些对象的指令。

举例:

1
2
3
4
5
6
// 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<String> userList = service.getUsernameList();
  1. 其中services.xml、daos.xml 就是一种配置元数据的形式。

    除了基于xml,还有基于注释的配置基于java的配置分别在2.5、3.0引入

  2. ApplicationContext context = new ClassPathXmlApplicationContext(..)通过加载配置实例化容器
  3. 后面就是使用容器获得bean。

Bean

上面提到的xml配置,里面配置了多了个BeanDefinition,每个BeanDefinition包含以下元数据:

  • 完整的类名
  • Bean行为相关的元素,如作用域、生命周期回调等
  • 对其他bean的依赖引用
  • 要在新创建的对象中设置的其他配置,例如,池的大小限制或要在管理连接池的bean中使用的连接数。

除了使用BeanDefinition外,ApplicationContext还允许注册用户自行创建的现有对象。通过容器的BeanFactory中registerSingleton和registerBeanDefinition来实现。

  • 名称
    id唯一,但name可以有多个。它们都可以默认不提供,spring会自动生成(按照约定规则生成,主要是小驼峰),但如果在应用中使用name来使用bean,最好配置上。
    也可以使用别名,如下这三个名字其实指向了同一个实例:
    1
    2
     <alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
    <alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
  • 实例化方法
    1. 通常的做法是配置类名然后通过其构造函数来new一个对象
    2. 另一种做法是调用某个工厂类的静态方法来创建一个bean
      1
      2
      3
      4
      5
      6
      7
      8
      #这是实例工厂方法
      <bean id="clientService"
      factory-bean="serviceLocator"
      factory-method="createClientServiceInstance"/>
      #这是静态工厂方法
      <bean id="clientService"
      class="examples.ClientService"
      factory-method="createInstance"/>

      依赖注入

      Dependency injection 是一个通过构造方法或工厂方法或者属性设置的方法,注入依赖的bean,使用依赖注入可以解耦数据之间的关系以及简化代码。

两种实现:

  1. 基于构造器的注入(工厂模式构建对象是一样的原理)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on a MovieFinder
    private MovieFinder movieFinder;
    // a constructor so that the Spring container can inject a MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
    }
    // business logic that actually uses the injected MovieFinder is omitted...
    }
  2. 基于setter方法的注入
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;
    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
    this.movieFinder = movieFinder;
    }
    // business logic that actually uses the injected MovieFinder is omitted...
    }
    注入的过程如下:
  3. 创建ApplicationContext并使用包含所有bean的元数据配置来初始化ApplicationContext。
  4. 对于每个bean,其依赖关系都以属性,构造函数参数或static-factory方法的参数的形式表示(如果使用它而不是普通的构造函数)。 实际创建Bean时,会将这些依赖项提供给Bean。
  5. 每个属性或构造函数参数都是要设置的值的实际定义,或者是对容器中另一个bean的引用