天天看点

spring ioc学习笔记

ioc的核心是DI,目的就是提供一种更简单的机制来设置组件依赖项,并在整个生命周期中管理这些依赖项。需要某些依赖项的组件通常被称为依赖对象,或者在ioc的情况下被称为目标对象。通常ioc可以分解为两种子类型:依赖注入和依赖查找,这些子类型被进一步分解为ioc服务的具体实现。通过这个定义可以清楚的看到,当谈论DI时,通常是在谈论ioc,而当谈论ioc时,并不总是在谈论DI(依赖查找也是ioc的一种形式)。使用依赖查找时,组建必须对依赖项的引用,而使用依赖注入时,依赖项将通过ioc容器注入组件,依赖查找有两种类型:依赖拉取,上下文依赖查找。依赖注入有两种类型:构造函数注入和setter注入。下面一一介绍

依赖拉取

依赖拉取是最常见的ioc类型,在依赖拉取中,根据需要从注册表中提取依赖项。

spring ioc学习笔记

Spring还提供依赖拉取作为一种检索框架所管理组件的机制:

public class DependencyPull {

public static void main(String[] args) {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/app-context.xml");

MessageRenderer mr = applicationContext.getBean("renderer",MessageRenderer.class);

mr.render();

}

上下文依赖查找

上下文依赖朝朝在某些方面与依赖拉取类似,查找是针对管理资源的容器执行的,而不是来自某个中央注册表,并且通常在某个设定点执行。

spring ioc学习笔记

依赖查找通过组件实现以下接口来进行工作,通过实现这个接口,一个组件可以向容器发送它想要获取依赖项的信号。

public interface ManagedComponent {

void performLookup(Container container);

public interface Container {

Object getDependency(String key);

public class ContextualizedDependencyLookup implements ManagedComponent {

private Depency depency;

public void performLookup(Container container) {

this.depency =(Depency) container.getDependency("myDependency");

当容器准备将依赖项传递给组件时,会依次调用每个组件的performLookup() 方法,然后组件可以使用container接口查找所需的依赖项。

构造函数注入

当在组件的构造函数中提供依赖项时,就会发生构造函数依赖注入。首先生命一个或一组构造函数,并将其依赖项作为参数,然后在组件实例化时由ioc容器将依赖项传递给组件。使用构造函数注入的一个显而易见的结果是,如果没有依赖项就不能创建对象,因此必须有依赖项。

public class ConstructorInjection {

private Dependency dependency;

setter注入

在setter注入中,ioc容器可以通过setter方法注入组件的依赖项。组件的setter方法公开了ioc容器可以管理的依赖项。使用setter注入的一个显而易见的后果是,可以在没有依赖项的情况下创建对象,然后可以通过调用setter来提供依赖项。实际上,setter注入是使用最广泛的注入机制,也是最简单的ioc机制之一。

public class SetterInjection {

注入与查找

现在问题来了,如果可以选择,应该使用哪种方法,注入还是查找?答案绝对是注入。一方面,注入对组件没有任何影响。另一方面,依赖拉取必须主动获得对注册表的引用并与其交互以获取依赖项。

如果使用注入,则可以自由的使用与ioc容器完全分离的类,而ioc容器通过手动为他们的协作者提供依赖对象;而如果使用查找,那么你的类总是依赖于容器定义的类和接口。查找的另一个缺点是难以独立于容器来测试类,而使用注入则可以非常容易的测试自己的组件,因为可以通过使用适当的构造函数或setter来提供依赖项。

setter注入和构造函数注入

现在问题又来了,我们已经选择使用注入了,但是是选择setter注入还是构造函数注入?答案是灵活使用

当在使用组件之前必须拥有一个依赖类的实例时,构造函数注入就特别有用了,但如果使用构造函数注入,则可以通过一种容器无关的方式声明对依赖项的需求,此外,构造函数注入也有助于实现不可变对象的使用。

setter注入在各种情况下都很有用。如果组件向容器公开了它的依赖项,并乐于提供自己的默认值,那么setter注入通常是实现此目的的最佳方法。setter注入的另一个好处是,它允许在接口上声明依赖项,尽管这种方法并没有前面的方法有用。setter注入还允许即时交换针对不同实现的依赖项,而无须创建父组件的新实例。Spring的JMX支持使这项功能成为可能。也许setter注入的最大好处是,它是注入机制中侵入性最小的。

一般来说,应根据使用情况选择注入类型。基于setter的注入允许在不创建新对象的情况下交换依赖项,并且还可以让类选择适当的默认值,而无须显式注入对象。当想要确保将依赖项传递给组件和设计不可变对象时,构造函数注入是一个不错的选择。