Spring系列第2篇:控制反转(IoC)与依赖注入(DI),晦涩难懂么?

Spring中有3个核心的概念:控制反转(Ioc)、依赖注入(DI)、面向切面编程(AOP),spring中其余的技术都是依靠3个核心的技术创建起来的,因此玩spring须要先对这3个概念有个深刻的理解。java

本文咱们先介绍其中的两个:控制反转和依赖注入,而aop咱们后面有专门的文章详解。算法

引出spring

有2个类,A和B,以下:spring

public class A{
    public void m1(){}
}

public class B{
    public void m1();
}

上面2个类都有一样的m1方法。数据库

如今咱们调用B的m1方法完成一些事情,而B中的m1方法须要调用A中的m1方法才能够完成这个事情,因此B的代码变成了下面这样:编程

public class B{

    private A a; // @1

    public B(){
        this.a = new A(); //@2
    }

    public void m1(){
        this.a.m1(); //@3
    }

}

分析一下上面代码:缓存

@1:B类中声明了一个A类型的属性a并发

@2:new了一个A对象,赋给了a属性ide

@3:B类中的m1方法中去调用a.m1()完成业务操做高并发

先说一下什么是依赖关系?测试

当a对象完成某些操做须要调用b对象中的方法来实现时,说明a依赖于对象b,a和b是依赖关系。

上面代码中B的m1须要调用A的m1方法,说明了B依赖于A

上面代码存在一些问题问题

B类中a对象的建立被写死在B的构造方法中了,若是咱们想在建立不一样的B对象的时候,使用不一样的a对象,此时是无能为力的;代码也不利于测试,因为B中a的建立被写死在构造方法中了,咱们想测试一下B中不一样a对象的效果,此时只能去修改B中的构造方法。

上面代码须要优化,B中a对象的建立不能写死,可让外部传入进去,调整一下变成了下面这样:

public class B{

    private A a;

    public B(A a){
        this.a = a;
    }

    public void m1(){
        this.a.m1(); 
    }
}

上面代码能够在建立B对象的时候,将外部建立好的a对象传入进去,此时a的控制权交给了使用者,建立B对象以下:

A a = new A();
B b = new B(a);
b.m1();

上面代码咱们再扩展一下,若是B类中还须要依赖不少相似于A的对象,好比须要依赖于C、D、E、F或者更多对象,首先是须要调整B的构造方法,修改老的构造方法不是很好,能够在B中新增一些构造方法。

可是使用B的时候就变成了下面这样:

A a = new A();
C c = new C();
D d = new D();
E e = new E();
F f = new F();
...
B b = new B(a,c,d,e,f,...);
b.m1();

使用者建立B对象以前,须要先将B依赖的对象都给建立好,而后B依赖的这些对象传递给B对象,若是有不少地方都须要用到B类型的对象,都采用这种new的写法,代码量比较大,也不方便维护,若是B中新增了依赖,又需采用new的方式先建立好被依赖的对象,而后将被依赖的对象填充给B对象。

上面建立对象以前,须要先将被依赖对象经过new的方式建立好,而后将其传递给B,这些工做都是B的使用者本身去作的,全部对象的建立都是由使用者本身去控制的,弊端上面也说了,代码量也比较大,代码耦合度比较高(依赖有调整,改动也比较大),也不利于扩展。

那么有没有更好的方式来解决这些问题呢?

上面B对象以及B依赖的对象都是使用者本身主动去控制其建立的,能不能找一个第三方来把这个事情给作了,好比给第三方一个清单,清单中告诉第三方我须要用到B对象以及B须要依赖的对象,而后由这个第三方去负责建立和组装B对象,使用者须要使用B对象的时候,只须要向第三方发起一个查找,若是第三方那边有B对象,直接将其内部组装好的B对象返回就能够了,整个系统中全部须要用到的对象均可以列个清单,让第三方帮忙创造,用的时候只须要向第三方索取就能够了,当B中依赖的对象有新增或者删除的时候,只须要去调整一下清单就能够了,这个事情spring已经帮咱们实现了。

spring容器

spring容器的概念,容器这个名字起的至关好,容器能够放不少东西,咱们的程序启动的时候会建立spring容器,会给spring容器一个清单,清单中列出了须要建立的对象以及对象依赖关系,spring容器会建立和组装好清单中的对象,而后将这些对象存放在spring容器中,当程序中须要使用的时候,能够到容器中查找获取,而后直接使用。

IOC:控制反转

使用者以前使用B对象的时候都须要本身去建立和组装,而如今这些建立和组装都交给spring容器去给完成了,使用者只须要去spring容器中查找须要使用的对象就能够了;这个过程当中B对象的建立和组装过程被反转了,以前是使用者本身主动去控制的,如今交给spring容器去建立和组装了,对象的构建过程被反转了,因此叫作控制反转;IOC是是面相对象编程中的一种设计原则,主要是为了下降系统代码的耦合度,让系统利于维护和扩展。

DI:依赖注入

依赖注入是spring容器中建立对象时给其设置依赖对象的方式,好比给spring一个清单,清单中列出了须要建立B对象以及其余的一些对象(可能包含了B类型中须要依赖对象),此时spring在建立B对象的时候,会看B对象须要依赖于哪些对象,而后去查找一下清单中有没有包含这些被依赖的对象,若是有就去将其建立好,而后将其传递给B对象;可能B须要依赖于不少对象,B建立以前彻底不须要知道其余对象是否存在或者其余对象在哪里以及被他们是如何建立,而spring容器会将B依赖对象主动建立好并将其注入到B中去,好比spring容器建立B的时候,发现B须要依赖于A,那么spring容器在清单中找到A的定义并将其建立好以后,注入到B对象中。

总结

  1. IOC控制反转,是一种设计理念,将对象建立和组装的主动控制权利交给了spring容器去作,控制的动做被反转了,下降了系统的耦合度,利于系统维护和扩展,主要就是指须要使用的对象的组装控制权被反转了,以前是本身要作的,如今交给spring容器作了

  2. DI依赖注入,表示spring容器中建立对象时给其设置依赖对象的方式,经过某些注入方式可让系统更灵活,好比自动注入等可让系统变的很灵活,这个后面的文章会细说。

  3. spring容器:主要负责容器中对象的建立、组装、对象查找、对象生命周期的管理等等操做。

  4. 下一篇开始详细讲解spring的使用了

Spring系列

  1. Spring系列第1篇:为什么要学spring?

更多好文章

  1. Java高并发系列(共34篇)

  2. MySql高手系列(共27篇)

  3. Maven高手系列(共10篇)

  4. Mybatis系列(共12篇)

  5. 聊聊db和缓存一致性常见的实现方式

  6. 接口幂等性这么重要,它是什么?怎么实现?

  7. 泛型,有点难度,会让不少人懵逼,那是由于你没有看这篇文章!

感谢你们的阅读,也欢迎您把这篇文章分享给更多的朋友一块儿阅读!谢谢!

路人甲java

▲长按图片识别二维码关注

路人甲Java:工做10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!