白话Spring -- Spring IOC

2019-10-18  本文已影响0人  散场前的温柔

白话Spring -- Spring IOC


  笔者虽然看过不少的技术博客,也用过Spring写过一年的代码,也修改过BUG,但是还是不理解到底什么是Spring?

  PS:不知道大家有没有同感,不是技术博客看不懂,那些个IOC、AOP也是能看懂,但就是感觉没有真正的理解透彻,总感觉还是有一层薄雾笼罩着,从而没办法随心所欲的使用Spring。

  笔者现在就通过这一系列文章,具象化的、图形化的说一下我对Spring的理解,不仅是对大家的一点帮助,也是笔者记录自己的心得感受,以免以后忘记了。




本文将通过:

  1. Spring是个啥?
  2. Spring-IOC是个啥?
  3. Spring-IOC能干啥?
  4. 为什么要用Spring?
  5. Spring怎么使用的?



    这几点来讲解一下我理解中的Spring。

1. Spring是个啥?

  度娘上和各种博客上都说Spring是一个Java开发框架,能方便我们开发代码,松耦合,方便实现各种功能。巴拉巴拉,各种各种。。。

  等会儿,我们先别管其他的。看到能简化代码,松耦合。嗯,这就是Spring。其他的什么框架什么的,管它呢,等我以后对Spring熟了再说吧。人脸都没看清,还指望我能对她能有多深入了解,对吧。

2. Spring-IOC是个啥?

  Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
  控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。     --百度百科

  上面是百度百科的解释,但是看了之后还是一头雾水。到底啥是IOC,怎么实现的呢?那么我们就来对比一下吧。

  我们大家以前写代码,一个类(Test)要引用另外一个类(Car)都是下面这样的:

// 代码块1

public class Car{
    private String name = "兰博基尼";
    public String getCarName(){
        return this.name;
    }
}

public class Test{
    Car car = new Car();
    public void test(){
        System.out.println("我获得了一辆" + car.getCarName());
    }
}

  我们先理解一下这句话 Car car = new Car(); 就是先声明一个Car类型的变量:car,然后再创建一个Car类型的实例赋值给 car ,也就是说这个car只是一个模子,用来存放这个实例的,我们使用的时候直接把car当成那个实例使用。

  大家可能会想这个东西很简单呀,为什么还要拿出来再说一遍?放心,这里我们待会儿就能用到。

  那么,我们来整体理解一下这段代码,就是Test类创建了Car类的实例,并调用了Car类的方法。也就是说,Test类是主动的去创建Car类的。

  那么,如果我们使用Spring-IOC呢?

  咱现在还不知道Spring-IOC到底是个啥,既然说能帮我们创建实例,那么咱现在就暂时把Spring-IOC理解成为"哆啦A梦"的百宝囊,我们要什么,Spring就能提供什么。

  那么我们接下来的代码就能这样写:

// 代码块2

public class Car{
    private String name = "兰博基尼";
    public String getCarName(){
        return this.name;
    }
}

public class Test{
    
    Car car;
    //此处假设Spring可以把实例赋值给car,但具体内容暂时忽略,后面会讲
    public void test(){
        System.out.println("我获得了一辆" + car.getCarName());
    }
}

  大家看到这段代码肯定一脸懵。这是啥,怎么变量car都没有赋值,值为null,就能调用方法了?不会报异常嘛。

  大家稍等片刻,别急别急,慢慢来。上面的是伪代码,不能被执行的。我在这里是先讲一下Spring-IOC能给我们做到什么效果。而Spring-IOC也确实可以自己创建一个Car类实例然后赋值给car变量。只是这些都是在后台执行的,我们看不到。所以我们在这里就索性认为Spring可以直接给变量赋值实例。也就是说到这里,car里就是有实例的,不是null。至于这里的代码怎么写,Spring-IOC怎么实现的,本文的后面会一一讲述。

  也就是说:Spring帮助Test类创建了实例然后又交给了Test类使用,而不用Test类自己去创建所需要的实例。换句话说,就是创建Car类实例的主动权由Test类变成了Spring。那么,我们这里就出现了一个概念:控制反转(IOC):将本来应由JavaBean(即Java类)创建实例的主动权交给了Spring,让Spring来创建实例,再将实例交给JavaBean使用。这种创建实例的控制权的改变,就称为控制反转。

  那么,这玩意儿有啥用?

3. Spring-IOC能干啥?

  通过上面的代码块1-2,我们并不能看出来什么,那么我就新写一个例子:

  这个例子是两个类实现了一个接口,然后实现一种多态的方式调用Car接口的实现类的实例。下面是我们以前的写法:

//代码块3

public interface Car{
    public String getCarName();
}

public class BaoShiJie implements Car{
    private String name = "保时捷";
    public String getCarName(){
        return this.name;
    }
}

public class FaLaLi implements Car{
    private String name = "法拉利";
    public String getCarName(){
        return this.name;
    }
}

public class Test{
    Car car = new FaLaLi();
    // Car car = new BaoShiJie();
    public void test(){
        System.out.println("我获得了一辆" + car.getCarName());
    }
}

  从上面可以看出,如果我们想从"法拉利"改成"保时捷",需要修改Test的代码,将创建FaLaLi类的实例修改成创建BaoShiJie类的实例。每一次改变都需要修改一次,如此大动干戈,显然这种方式不太好。

  那么,使用Spring-IOC呢?

  我们在代码块2中假设了,Spring-IOC可以直接给变量赋值实例,那么代码块3中的car变量我们是否也可以通过这种方式赋值呢?有人可能会思考,即使可以,那程序怎么分辨我们具体要什么车呢?如此是否我们同样能假设我们可以告诉Spring-IOC我们需要哪一辆呢?

// 代码块4

public interface Car{
    public String getCarName();
}

public class BaoShiJie implements Car{
    private String name = "保时捷";
    public String getCarName(){
        return this.name;
    }
}

public class FaLaLi implements Car{
    private String name = "法拉利";
    public String getCarName(){
        return this.name;
    }
}

public class Test{
    Car car;
    // 此处告诉Spring-IOC我需要法拉利/保时捷,假设Spring-IOC就会把相应车的实例赋值给变量car
    public void test(){
        System.out.println("我获得了一辆" + car.getCarName());
    }
}

  哦哦哦,出来了,大家发现没有,Test类里没有出现FaLaLi类或者BaoShiJie类的身影,我们告诉Spring-IOC我们需要什么车,完全可以通过String的方式,如果这个String还是通过外部参数形式导入的话,那么我们在换车的时候,就完全不同修改Test类了。













上一篇 下一篇

猜你喜欢

热点阅读