欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

什么是控制反转(IoC)?

程序员文章站 2022-07-12 13:58:40
...
  • ????:前面ssh整合中,spring起到的作用是帮忙创建一些实例,如service的dao成员变量,这么做的好处是什么?是怎么办到的?我想了解一下。
  • ????:为什么要spring来创建实例,而不是我们的调用类直接创建被调用类的实例呢?这就有必要了解一个思想,IoC控制反转。
  • ????:什么是IoC啊?
  • ????:来看一个具体的栗子:
    大家想必都知道这么一个梗吧:你站在这里不要动我去买几个橘子
    什么是控制反转(IoC)?
    ①首先为什么要站在原地呢?我们来分析一下自己去买的情况
    先来定义一个son类,该类会调用orangSeller类,实现买橘子的方法
public class Son {
    //找到卖橘子的
    OrangeSeller orangeSeller = new OrangeSeller();
    //买橘子
    public void buyOrange() {
        orangeSeller.sell();
    }
}

自然我们还需要定义橘子销售商类orangSeller,要把橘子卖给son类

/*
橘子销售商
 */
public class OrangeSeller {

    /*
    卖橘子
     */
    public void sell() {
        System.out.println("卖橘子咯");
    }

}

在上面的代码中,调用类需要自己创建被调用类,代入场景就是son需要自己去买橘子,而且只跟特定的一个销售商买,要是该销售商没橘子了我们就买不到了…跟特定的一个销售商高度耦合在一起明显不理智。要是这个销售商没橘子卖了,或者我们突然不想买橘子改想买苹果了,那我们需要去改写Son类的成员变量,一个还好,多了就会显得烦琐。这时我们想到用多态的方法,实现一个销售商接口。

package spring.IoCDemo;
/*
销售商接口
 */
public interface Seller {
    public void sell();
}

橘子销售商实现该接口

package spring.IoCDemo;
/*
橘子销售商
 */
public class OrangeSeller implements Seller {

    /*
    卖橘子
     */
    public void sell() {
        System.out.println("卖橘子咯");
    }

}

再创建一个苹果销售商

/*
苹果销售商
 */
public class AppleSeller implements Seller {
    public void sell() {
        System.out.println("苹果有卖");
    }
}

这样一来我们就可以多跑几家买到心仪的水果了


public class Son {
    //找到卖橘子的
    Seller seller = new OrangeSeller();
    //找到卖苹果的
    //Seller appleSeller = new AppleSeller();
    //买水果
    public void buyOrange() {
        seller.sell();
    }

}

但是这样做我们还是需要自己去new一个被调用接口的实体,还是得自己亲自跑一趟,要是错过了站点怎么办?(依旧需要自己去绑定接口实现类,不灵活)
②单一指责原则,son只负责吃到橘子,所以有没有办法让son不去负责销售商的选择?(让父亲帮son去买)
改写Son类,将橘子销售商的实例作为参数传递进来

public class Son {

    private Seller seller;

    public void setSeller(Seller seller){
        this.seller = seller;
    }
    //买橘子
    public void buyOrange() {
        seller.sell();
    }

}

父亲去帮儿子买橘子

public class Parent {

    OrangeSeller orangeSeller = new OrangeSeller();
    public void execute() {
        Son son = new Son();
        son.setSeller(orangeSeller); //你站在原地别动
        son.buyOrange(); //我去帮你买水果
    }
}

这样儿子就能安心等车加吃橘子啦。儿子与销售商之前也不再紧密耦合,他们之间的关系由parent统一管理,这里的parent就是我们的spring容器啦

  • 总结
    现在我们可以来理解一下IoC的概念了,IoC(Inverse of Control)字面意思就是控制反转,包括两方面的内容:
    一是控制;
    二是反转。
    所谓控制,对应前面的栗子,指的就是选择销售商的控制权;
    反转就是指这种控制权从son中移除,儿子不用亲自去买橘子,而是让父亲买来。
    对软件来说,即某一接口的具体实现类的选择权从调用类中移除,转交给第三方决定,即由spring容器借由bean配置来进行控制。
    IoC也称依赖注入(DI)即让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一实现类的依赖

我们可以认为上面提到的第三方是应用平台,或者更具体地说是IoC容器。通过使用IoC容器,对象依赖关系的管理被反转了,转到IoC容器中来了,对象之间的相互依赖关系由IoC容器进行管理,并由容器完成对象的注入。这样就在很大程度上简化了应用的开发,把应用从复杂的对象依赖关系管理中解放出来。简单地说,因为很多对象的依赖关系的建立和维护并不需要和系统运行状态有很强的关联性,所以可以把我们在面向对象编程中常常需要执行的诸如新建对象、给对象引用赋值等操作交由容器统一完成。这样一来,这些散落在不同代码中的功能相同的部分就集中成为容器的一部分,也就是成为面向对象系统的基础设施的一部分。
如果对面向对象系统中的对象进行简单地分类,会发现除了一部分是数据对象外,其他有很大一部分对象都是用来处理数据的。这些对象并不会经常发生变化,是系统中基础的部分。在很多情况下,这些对象在系统中以单件的形式存在就可以满足应用的需求,而且它们也不常涉及数据和状态共享的问题。如果涉及数据共享方面的问题,需要在这些单件的基础上做进一步的处理。
同时,这些对象之间的相互依赖关系也是比较稳定的,一般不会随着应用的运行状态的改变而改变。这些特性使得这些对象非常适合由IoC容器来管理,虽然它们存在于应用系统中,但是应用系统并不承担管理这些对象的责任,而是通过依赖反转把责任交给了容器(或者说平台)。了解了这些背景,Spring IoC容器的原理也就不难理解了。在原理的具体实现上,Spring有着自己的独特思路、实现技巧和丰富的产品特性。

上一篇: Dubbo+Spring定时器

下一篇: Spring IOC