在spring里,IOC(反转控制)通常伴随着DI(依赖注入)出现,IOC是一种思想,DI是它的一种实现手段
基础接口:
- BeanFactory
- ApplicationContext
其中Application增加如下特性:
- 更好的与springAOP模块集成
- Message resource 处理(国际化部分)
- 事件的发布
- 应用层特定的上下文,例如Web应用程序中使用的WebApplicationContext。
简而言之,BeanFactory提供了配置框架和基本功能,而ApplicationContext是BeanFactory的完整超集,在本文介绍IOC时都统一使用ApplicationContext来作为IOC容器。
容器
器通过读取配置元数据来获取有关要实例化,配置和组装哪些对象的指令。
举例:
1 | // create and configure beans |
- 其中services.xml、daos.xml 就是一种配置元数据的形式。
- ApplicationContext context = new ClassPathXmlApplicationContext(..)通过加载配置实例化容器
- 后面就是使用容器获得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"/> - 实例化方法
- 通常的做法是配置类名然后通过其构造函数来new一个对象
- 另一种做法是调用某个工厂类的静态方法来创建一个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
2
3
4
5
6
7
8
9public 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...
} - 基于setter方法的注入注入的过程如下:
1
2
3
4
5
6
7
8
9public 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...
} - 创建ApplicationContext并使用包含所有bean的元数据配置来初始化ApplicationContext。
- 对于每个bean,其依赖关系都以属性,构造函数参数或static-factory方法的参数的形式表示(如果使用它而不是普通的构造函数)。 实际创建Bean时,会将这些依赖项提供给Bean。
- 每个属性或构造函数参数都是要设置的值的实际定义,或者是对容器中另一个bean的引用