Java工程师的咖啡

Spring源码解读,认识Spring IOC容器

2020-02-20  本文已影响0人  javap

知识要点:

什么是Spring IoC容器

什么是IoC

什么是依赖倒置

为什么需要Spring IoC

什么是Spring IoC容器

Spring Ioc容器的最主要作用就是:完成对象的创建管理和依赖注入等 。

什么是IoC

IoC(Inversion of Control,控制反转)是Spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由Spring来负责控制对象的生命周期和对象之间的关系。
既然提到了IoC,我们就不得不提及设计模式中的六大原则。因为原则之一的“依赖倒置”跟IoC有很大的关系。
控制反转(IoC)是DIP(Dependence Inversion Principle,依赖倒置原则)的一种具体实现方式。 依赖注入(DI,Dependence Injection)是IoC的一种具体实现方式,用来实现依赖倒置。

设计模式六大原则

class Laptop {
    public void start(){
        System.out.println("Laptop启动....");
    }

    public void run(){
        System.out.println("Laptop运行....");
    }
}

class Programmer {
    Laptop laptop = new Laptop();

    // 编写代码
    public void coding(){
        laptop.start();
        laptop.run();
    }
}

上面这段代码的问题在:如果某一天业务需求要改换成台式电脑(Desktop),这个修改工作肯定是避免不了的。而且工程越复杂修改量越大。怎么处理好呢?
如果我们不进行解耦,它们的关系就会是这样:



而且,在采用面向对象方法设计的软件系统中,底层实现都是由非常多的对象组成,所有的对象通过彼此的合作,最终实现系统的业务逻辑。 随着应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系。这是致命的,不管对于开发还是维护来说。

什么是依赖倒置

如何降低系统之间、模块之间和对象之间的耦合度,是软件工程永远追求的目标之一。为了解决对象之间的耦合度过高的问题,我们使用IoC理论来实现对象之间的“解耦”。
上面的代码,对象和对象之间的耦合太严重。那我们应该如何进行解耦呢?
我们再来看一段代码:

interface Computer {
    public void start();
    public void run();
}

class Laptop implements Computer{
    public void start(){
        System.out.println("Laptop启动....");
    }

    public void run(){
        System.out.println("Laptop运行....");
    }
}

class Desktop implements Computer{
    public void start(){
        System.out.println("Desktop启动....");
    }

    public void run(){
        System.out.println("Desktop运行....");
    }
}

class Programmer {
    Computer c;
    
    Programmer(Computer c){
        this.c = c;
    }

    public void coding(){
        c.start();
        c.run();
        c.stop();
    }

    // DI  解决依赖问题
    // IOC 解决实例化问题
    public static void main(String[] args){
        Computer c = new Desktop();
        Programmer p = new Programmer(p);
        p.coding();
    }
}

在这段代码里面,就体现了几个设计模式中的原则,当然也包括“依赖倒置”—— 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
上面的第一段代码中的类是Programmer类依赖了具体Laptop类,如Programmer中的use方法drive,这样Programmer就对具体的Laptop产生了依赖,如果这个时候想要使用其它的工具如Desktop(桌面台式电脑),就需要修改Programmer类。因此我们需要抽象接口Computer,这样Programmer只需要依赖Computer即可,至于到底选择哪种电脑,就交给IOC容器,进行依赖注入即可。

高层模块不应该依赖底层模块

这句话是依赖倒置的核心。指的是概念的自包含,上层模块不应该去依赖具体的某个底层提供方。在设计系统时,常常会采用分层的方式:数据访问层,业务逻辑层,展示层等,而每一层会依赖下层的API,这样导致的问题就是难以替换下层的提供方。那应该如何做呢?业务逻辑层需要有自己的数据访问规范,也就是SPI,然后数据提供层去适配这个SPI,这样如果替换了下层的数据层之后对业务逻辑层也不会产生影响。

抽象不应该依赖细节,细节应该依赖抽象

有了上面的概念之后,自然也就有了依赖抽象而非细节,因为上层制定的是SPI(Service Provider Interface), 也就是一种通用的实现接口,由不同的实现方来提供实现。另外一般实现方也会提供自己的API接口供其他应用来使用,因此一般实现方会在自己的API上面封装一层SPI的适配层来提供给上层使用。
依赖抽象而非细节也是依赖注入与IOC实现的基础。

为什么需要Spring IoC

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,如下图:



在Spring中通过IoC容器来创建这些对象,即由Ioc容器来控制对象的创建,控制外部资源获取(如:对象或资源文件等)。而控制反转在Spring中的体现就是:由容器来创建及注入依赖对象,对象只是被动的接受依赖对象,获取依赖对象的方式也被反转( 与反转相反的做法:通常由我们自己在对象中直接获取依赖对象 )。
总结:IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

上一篇下一篇

猜你喜欢

热点阅读