详解Spring Ioc(控制反转)

Spring Ioc

控制反转是一个比较抽象的概念,可以举例来说明。
生活中,人们要用到一种东西,人们的基本想法就是找到东西,比如想喝果汁,在没有饮品店的日子里,最直接的做法就是,买果汁机,水果,准备开水。这时我们“主动”创造的过程,也就是一杯果汁需要主动去创造。
而现在果汁店遍地都是,想喝果汁,第一想法就是打开手机,搜索果汁店,根据自己喜欢的口味下单,等待外卖小哥来送果汁,注意:这里我们没有“主动”创造果汁,是由饮品店创造的,而不是我们,但是也达到了要求是不是。

通过上面的简单的例子,我们从中可以看到控制反转的思想,现实中系统的开发者是一个团队,团队由许多开发者组成。假设我在一个电商网站负责开发工作,我比较熟悉商品交易流程,但对财务不怎么熟悉,而团队中有些人员对于财务处理十分熟悉,在交易的过程中,商品交易流程只需要调度财务的相关接口,才能得以实现,那么我们的期望应该是:

  1. 熟悉财务流程的成员开发对应的接口
  2. 接口逻辑尽量简单,内部复杂的业务并不需要自己去了解,我只需要通过简单的调用就能使用
  3. 通过简单的描述就能获取这个接口实例,且描述应该尽量简单

其实这完全跟果汁的例子进行类比,果汁就相当于财务接口,而熟悉财务流程的同事就等同于饮品店,而我们根据喜欢的口味下单就等同于财务接口实例的描述。
生活中的例子与程序开发是多么的相似,但这里有个需要注意点:财务接口对象的创建不是自己的行为,而是财务同事主动创建,也达到了你的要求,在潜意识里你会觉得对象应该由你来创建,但是事实上这并不是你真正的需求。因为你对这一领域不精通,这个时候可以把创建对象的主动权交给别人,这就是控制反转的概念。对于财务开发者而言,他们也不了解交易系统的细则,他们同样希望由你来创建交易接口。为了更好的阐述上面的抽象描述,我们使用java代码的形式模拟主动创建和被动创建的过程。

主动创建对象

如果我们需要一杯果汁,那就等同于需要水果,开水,糖等,搅拌机(工具·)
主动创造果汁,需要创建对应的对象–JuiceMaker(果汁生成器)和Blender(搅拌机)

public class Blender {
    /**
     * 搅拌机
     * @param water 水
     * @param fruit 水果
     * @param sugar 糖
     * @return
     */
    public String mix(String water,String fruit,String sugar){
        String juice = "这是一杯由"+water+"\n水果:"+fruit+"\n糖量:"+sugar+"\n组成的果汁";
        return juice;
    }
}
@Getter
@Setter
public class JuiceMarker {
    private Blender blender = null;//搅拌机
    private String water;//水描述
    private String fruit;//水果
    private String sugar;//糖分描述

    public String makeJuice(){
        blender = new Blender();
        return blender.mix(water,fruit,sugar);
    }
}

主动创造果汁,需要我们实现自己可能不太熟悉的工作–如何搅拌果汁,比如这里的mix方法,显然不是一个好的方法,而对象果汁(juice)是需要依赖水(water)、水果(fruit)、糖(sugar)和搅拌机(blender)去实现的,这样的关系也会需要我们自己去维护,如下图:
在这里插入图片描述
现实中,一个复杂的系统界面对着成百上千种情况,如果都需要这样的维护,那么会十分复杂,更多的时候,我们并不希望了解这类过程,因为有些东西我们并不需要知道过程,只需要获得最后的结果。正如果汁的例子那样,现实生活中我们更加希望是通过对饮品店的描述得到果汁,只想对结果进行描述,得到我们所需要的东西,这就是被动创建对象。

被动创建对象

假设已经提供了果汁制造器(juiceMaker2)那么只需要对其进行描述就可以得到果汁了。假设饮品店还会给我们提供这样一个描述(source),它的描述如下:

@Getter
@Setter
public class JuiceMarker2 {
    private String beverageShop = null;
    private Source source = null;
    
    public String makeJuice(){
        String juice = "这是一杯由"+beverageShop+"饮品店,提供的"+source.getSize()+source.getSugar()+source.getFruit();
        return juice;
    }
}
@Setter
@Getter
public class Source {
    private String fruit;//类型
    private String sugar;//糖分描述
    private String size;//大小杯
}

显然我们不需要去关注果汁是如何制造出来的。系统采用XML对这个清单进行描述,如下代码:

<bean id="source" class="com.lifly.ioc.Source">
        <property name="fruit" value="橙汁"/>
        <property name="sugar" value="少糖"/>
        <property name="size" value="大杯"/>
    </bean>

这里对果汁进行了描述,接着就是选择饮品店,假设选择的是蓝莓,那么会有以下描述:

    <bean id="juiceMaker2" class="com.lifly.ioc.JuiceMarker2">
        <property name="beverageShop" value="蓝莓"/>
        <property name="source" ref="source"/>
    </bean>

这里将饮品店设置为蓝莓,这样就指定了蓝莓为我们提供服务,而订单则引用我们之前的定义,这样使用下面的代码借得到了一杯果汁了

    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        JuiceMarker2 juiceMaker2 = (JuiceMarker2) context.getBean("juiceMaker2");
        String s = juiceMaker2.makeJuice();
        System.out.println(s);
    }
}

这个过程,果汁是由蓝莓所制造的,我们并不关系制造的过程,我们所关心的是对果汁如何描述,选择哪个店去制造,这才是现今人们的习惯,这个理念也可以用于程序代码
在这里插入图片描述
显然这个过程中我们不需要了解饮品店是如何工作的,我们只需要关注如何描述,就能得到想要的结果。

Spring Ioc简述

有了上面的实例,下面来说下控制反转的概念:
控制反转****是一种通过描述(在Java中可以使XML或者注解)并通过第三方去产生或获取特定对象的方法。
正如被动创建的果汁是通过XML配置的描述所得到的,而在spring中实现控制反转的是Ioc容器,其实现方式是依赖注入(Dependency Injection,DI),正如上述的例子,果汁制造器依赖于饮品店和订单去制造果汁的,而饮品店是别人去创造的,我们只需要它能生产果汁就可以了,并不需要去理解如何创建果汁。
spring会提供Ioc容器来管理对应的资源,正如上面的例子中的饮品店和订单资源,由于它们形成依赖关系,其中果汁制造器用到饮品店和订单两个资源。同样的,这个也用于编码实战,如以下例子。
当熟悉财务的同事完成对财务接口模块的开发,就可以将其发布到Spring Ioc的容器里,这个时候你只需要过程描述得到对应的财务接口,就可以完成对应的财务操作了。而财务模块是如何工作的,它有需要那些依赖对象,都是由熟悉模块的同事完成的,这些并不需要你去理解,你只需要它能完成对应的财务操作就可以了。同样,对于熟悉交易的你,也可把交易接口模块发布到Spring Ioc容器中,这样财务开发人员就可以通过容器获取交易接口得到交易明细了,交易模块如何工作,又依赖于哪些对象,他也是不需要知道的,可见Spring Ioc容器带来了许多使用的便利。

在这里插入图片描述

对于测试人员也一样,也许他早早把财务模块测试好了,需要测试交易模块,他并不希望非常细致的了解交易模块,他只需要从Spring Ioc容器中获取就可以了。而他的测试代码也只需要从Spring Ioc容器获取交易模块的内容,至于内部复杂的依赖并不是他所关注的内容,这样就有利于测试人员对模块的测试,降低测试人员测试的复杂度。
这就是一种控制反转的理念,虽然这个理念的一个坏处是理解上的困难,但是它最大的好处在于降低对象之间的耦合,在一个系统中有些类,具体如何实现并不需要去理解,只需要知道它有什么用就可以了。只是这里对象的产生依赖于Ioc容器,而不是开发者主动的行为。主动创建的模式,责任归与开发者,而在被动的模式下,责任归于Ioc容器。基于这样的被动形式,我们就说对象被控制反转了。
基于降低开发难度,对模块解耦,同时也更加有利于测试的原则,Spring Ioc在各大领域中被广泛应用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_lifly

点喜欢就是最好的打赏!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值