关于Spring的那些事儿(一):什么是IOC,为什么要IOC,什么是DI?

关于Spring的那些事儿(一):什么是IOC(控制反转),为什么要IOC(控制反转),什么是DI(依赖注入)?

1.一个小例子

为了解释什么是IOC(控制反转),及为什么要IOC(控制反转),我们先讲一个故事:
唐僧出发去西天取经,一路上危险重重,这天他遇到了孙悟空,并将其收为徒弟,那么我们说唐僧依赖孙悟空,这个事情反映到代码上,最简单的是这样写。

public class WuKong {
    public void fight() {
        System.out.println("孙悟空打妖怪!");
    }
}

public class TangSeng {
    private WuKong wuKong = new WuKong();

    /**
     * 唐僧取经
     */
    public void qujing() {
        wuKong.fight();
    }
}

然而唐僧接着取经,又遇到了猪八戒,那我们不得不把唐僧改成下面这样,并增加一个猪八戒。

public class BaJie {
    public void fight(){
        System.out.println("猪八戒打妖怪!");
    }
}

public class TangSeng {
    private WuKong wuKong = new WuKong();
    private BaJie baJie = new BaJie();

    public void qujing() {
        wuKong.fight();
        baJie.fight();
    }
}

那么,如果唐僧遇到妖怪时,悟空不在怎么办呢?如果唐僧又收了别的徒弟呢?我们是不是需要继续修改唐僧呢?

2.IOC(控制反转)

然则程序猿之精力有限,唐僧之欲无厌。
这个时候程序猿请伟大的观音菩萨出场,菩萨觉得唐僧的徒弟都要会打妖怪,并且唐僧也别管收了几个徒弟了,观音给你几个就收几个吧。

public interface TuDi {
    void fight();
}

public class TangSeng {
    private List<TuDi> tuDis;

    /**
     * 唐僧取经
     */
    public void qujing() {
        for (TuDi tuDi : tuDis) {
            tuDi.fight();
        }
    }

    public void setTuDis(List<TuDi> tuDis) {
        this.tuDis = tuDis;
    }
}

public class GuanYin {
    public void setTuDis(TangSeng tangSeng) {
        List<TuDi> tuDis = new ArrayList<TuDi>();
        TuDi wukong = new WuKong();
        TuDi bajie = new BaJie();
        tuDis.add(wukong);
        tuDis.add(bajie);
        tangSeng.setTuDis(tuDis);
    }
}

这样的话唐僧再也不用控制有几个徒弟了,他自己不需要new出徒弟,他只需要安心取经,徒弟的事儿就交给观音管了,这里可以说是(IOC)控制反转了。

3.DI(依赖注入)

观音通过setTuDis()方法把唐僧依赖的徒弟注入到唐僧的属性中,这种动作叫DI(依赖注入)。这样使得唐僧和他的徒弟的耦合关系降低了。
但是显然用观音这个类还是没解决我们的问题,我们虽然不用修改唐僧了,但是我们面对不同的需求还是需要修改观音这个类来实现不同功能。

4.Spring的作用

这时Spring出场了,它为我们提供的Spring容器可以很好的完成IOC的功能,并且只需要我们做相应的配置就可以把需要的依赖注入。
在Spring的官方文档中是这样介绍IOC和DI的:

This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

翻译成中文:本章介绍了控制反转原则的Spring框架实现。IOC也叫依赖注入(DI)。这过程中对象仅通过构造参数,工厂方法的参数,或在构造和工厂产生实例后set属性的方式定义其依赖项(与该对象合作的对象),然后容器在创建这些bean时注入这些依赖项。以上过程从根本上说是“Bean自己通过直接构造或例如‘服务定位模式’的机制来控制和定位它的依赖”这个过程的逆过程(因此称为控制反转)。

也就是说Spring为我们提供了一个Spring容器(观音),他帮助Bean(唐僧)管理徒弟(依赖),而不是让Bean(唐僧)自己创建管理依赖(徒弟)。

我们在pom.xml引入Spring依赖的jar包

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
    </dependencies>

在resource目录下创建一个Spring配置的xml,我这里取名为application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        
    <bean id="wukong" class="com.chen.ioc.WuKong"/>
    <bean id="bajie" class="com.chen.ioc.BaJie"/>
    <bean id="tangseng" class="com.chen.ioc.TangSeng">
        <property name="tuDis">
            <list>
                <ref bean="wukong"/>
                <ref bean="bajie"/>
            </list>
        </property>
    </bean>
</beans>

我们可以不需要观音类,靠Spring的配置实现了我们想要的依赖注入,从而达到了我们控制反转的目的。
下面做一个测试。

import com.chen.ioc.TangSeng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

        TangSeng tangSeng = (TangSeng) context.getBean("tangseng");
        tangSeng.qujing();
    }
}

运行main方法结果如下:
在这里插入图片描述

5.总结

  1. IOC(控制反转)是一种程序设计思想,它是指将调用对象(例子里的唐僧)对依赖对象(例子里的徒弟)的控制权反转,交给第三方,在Spring框架下就是交给Spring容器管理。
  2. IOC的目的是让调用对象(唐僧)直接使用依赖对象(徒弟)完成自己的工作就可以,而不需要管依赖对象的实例创建,从而解除调用对象(唐僧)与依赖对象(徒弟)之间的耦合关系,使得程序维护工作量下降。
  3. DI(依赖注入)是IOC(控制反转)的一种实现方式,他是指通过第三方(Spring容器)将依赖对象注入,从而实现控制反转。

6.预告

这是我的第一篇博客,写得不好,不知道有没有人看,后面的博客将会写关于Spring的配置说明,Spring IOC依赖注入方式等内容,再之后会写框架源码的个人解读,希望自己能完成任务吧。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值