spring框架核心思想之ioc控制反转

IoC与DI

IoC和DI是Spring的两个核心概念,很多人都把它们视为相同的东西,但事实并非如此。
IoC(Inversion of Control):控制反转。
DI(Dependency Injection):依赖注入。

为了方便理解,先给出结论:

控制反转是目的,依赖注入是实现控制反转的手段。

控制反转是一种面向对象的思想,它是一种宽泛的概念,只要一个类将对它内部状态的控制权交由其他机制去完成即为『控制反转』。控制反转是为了降低类与类之间的耦合度。

而Spring采用依赖注入这一具体的手段来达到控制反转的目的

依赖注入详解
一个类内部往往有很多成员变量,如:

class A {
    private Person chaimm;
}

上述代码在面向对象中可以描述为:

  • A类和Person类之间存在依赖关系;
  • A依赖于Person;
  • A为依赖类;
  • Perosn为被依赖类;

通常情况下,依赖类需要自己去创建并维护被依赖类的对象,如:

class A {
    private Person chaimm = new Person();
}

但依赖注入的做法是:将被依赖对象的创建与维护工作交由专门的机构,而依赖类中只需要声明所需要的成员变量。
也就是说,依赖类原本需要主动去获取对象,但采用依赖注入后对象由第三方机构提供,自己仅需声明需要什么对象即可。
这样做的目的就是为了降低两个类之间的耦合程度。
PS:在Spring中,那个创建、管理对象的机构就称为『IoC Service Provider』。

但此时还没体现出依赖注入能降低耦合度这一点,只有当依赖注入与面向接口编程结合起来,才能真正发挥依赖注入的优势。接下来先介绍一下『面向接口编程』。

什么是面向接口编程?
一个类依赖其他类的目的是为了获取其他类所提供的服务,可能这种服务有多种实现,我们可能需要根据不同的场景使用不同的实现。此时,我们可以使用多态,将同一功能的多种实现抽象出一个接口,并为所有实现定义一套相同的API。在使用时声明接口类型的变量而非实现类的变量,并将实现类的对象赋给接口变量,最后用接口变量去调用实现类的服务,如:

class A {
    private Super super = new SuperImpl_1();

    public static void main ( String[] args ) {
        // 使用Super提供的服务
        super.method_1();
        super.method_2();
        super.method_3();
    }
}

这样,当想使用SuperImpl_2提供的功能时,只需替换Super的实现类,其他地方不做任何变化:

private Super super = new SuperImpl_2();

上述过程就是面向接口编程的思想:若某一类服务有多种不同的实现,我们需要抽象出一个接口,并在接口中定义一套API。在使用时声明接口类型变量,并用实现类的对象赋值。接下来通过接口类型的变量调用服务即可。当功能发生变化时,仅需替换实现类即可。

在面向接口编程的基础上使用依赖注入的好处
上述过程如果要换一种实现,就必须要修改A类的代码,再重新编译。而使用了依赖注入后,由于依赖类不需要自己创建维护被依赖对象,该过程由IoC Service Provider完成。因此,当需要替换实现类时,只需在IoC Service Provider中修改,被依赖类、依赖类都不会受到影响,此时这两个类是松耦合的。

依赖注入的三种方式

下面介绍三种方式,将被依赖对象注入给依赖类。

1. 构造器注入

将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。

优点:
对象初始化完成后便可获得可使用的对象。

缺点:
1. 当需要注入的对象很多时,构造器参数列表将会很长;
2. 不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。

2. setter方法注入

IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。

优点:
灵活。可以选择性地注入需要的对象。

缺点:
依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。

3. 接口注入

依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。
接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。

缺点:
侵入行太强,不建议使用。

PS:什么是侵入行?
如果类A要使用别人提供的一个功能,若为了使用这功能,需要在自己的类中增加额外的代码,这就是侵入性。



作者:大闲人柴毛毛
链接:https://www.zhihu.com/question/23277575/answer/247023315
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/zhuyoushaonian/article/details/78883001