Spring初学笔记(一):Spring IOC的理解

关于依赖注入、控制反转

 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

  在我看来,这句话已经很好的体现了出来IOC思想在编程中的体现形式,而采用这样的思想,可以大大降低类与类之间的耦合度,便于代码的扩展。

  这里,我们看一个简单的例子:

  我们假设有人和车,他们的类分别如此:

public interface Car {
    public void run();
}

 

public interface Person {
    public void Travel();
}

  首先定义两个接口,表示要实现的车的功能和人的功能,而在实现人的功能时,旅游总不能光着脚出去吧,假设我们需要一辆车才能出行:

public class BenzCar implements Car{
    @Override
    public void run() {
        System.out.println("奔驰车在跑");
    }
}
public class Man implements Person {
    private Car car;
    public Man(){
        car = new BenzCar();
    }
    @Override
    public void Travel() {
        System.out.println("我有车了");
        car.run();
    }
}

  这是对应实现好的人类和车类,其中人类依赖于车类,他现在要自己创建一个车的对象,才能实现对应的功能。

  我们测试一下这个代码可不可以运行:

public class Test {
    public static void main(String[] args) {
        Person person = new Man();
        person.Travel();
    }
}

  执行以后,代码可以正常运行,但现在有一个问题,如果这个人过几天有钱了,不想用奔驰了,想换车,那怎么办呢。现在的代码,有一个很明显的问题,就是人和车类的耦合度太高,其原因就是在Man类的内部,自己创造了对应车类的对象,这就导致如果要想修改,只能对Man类的源码进行修改,这也就不符合“对修改关闭,对扩展开放”的原则了。

  对这个问题的解决办法就是:不要从内部创建对象,而是由外部传入对象,你只要接收就可以了。

  在更改后的代码为:

public class Man implements Person {
    private Car car;
    public Man(Car car){
        this.car = car;
    }
    @Override
    public void Travel() {
        System.out.println("我有车了");
        car.run();
    }
}

  将对应的Car类对象的生成方法,由自己new出来,变成通过构造参数传入(当然传入的方法不止一种,像set之类的方法也是可以的,这里只以构造方法为例)

  现在对于Man类的扩展问题,我们已经解决了,就算他换成什么车,我们都可以直接在main函数中创建对应的对象,然后直接传入即可。

  做到这里,像我这样从来没有大型编程经验的人就觉得已经很好了呀,我不用修改源代码,只要自己在主函数中创建对象,通过我设定的构造器呀set呀等方法传入就可以让程序正常运行啦。

  但有多年开发经验的程序员们觉得还不大行,确实这样可以满足了代码复用和开闭原则,但你这样做有一个前提条件,就是你自己熟悉自己所写的全部类,可以明确他们的关系,才能够创建出对应的实体类,但如果是多人开发呢,如果一个人只负责一个模块,那会发生什么样的情况。

  从上面我们可以看到,创建一个人的对象,我们需要显式地注入Car的对象,我们很清楚这一点,所以我们可以创造出man类的对象,但如果是多人合作,比如我是写service层的人员,我想调用person的travel()接口,但发现没有实体类,我需要构建。我new一个实体类,结果编译器报错误,我找了半天没找出来哪里有错,最后对Dao管理的人给我说,这个你要传进去一个Car类的对象,其中Car类对象有.xxx,sss之类。

  我只是需要调用对象的接口,但这样的注入方法,让我必须清楚对象是如何创建的,而且还要为这个构建去new一个Car对象,这些都是完全不应该由我这样一个写service层的人来做的工作,为了解决这个问题,我们可以采用工厂模式。

  先创建一个单例的工厂:

public class Factory {
    private Factory() {
    }

    public static Factory getInstance() {
        return inner.instance;
    }

    private static class inner {
        private static final Factory instance = new Factory();
    }

}

  在工厂中,我们可以创建Man对象:

public Person getMan(){
        return new Man(new BenzCar());
    }

  这样,我们在外部调用的时候,只需要获得工厂,然后通过工厂的方法得到所需对象了,不再需要关心对象到底是如何生成的了。

public static void main(String[] args) {
        Factory factory = Factory.getInstance();
        Person person = factory.getMan();
        person.Travel();
    }

   

  原本是调用者直接创建对象,现在改成了通过工厂这个容器,来直接获取对象。

  这样,通过工厂方式+注入对象的方法,我们实现了类与类之间的解耦,也完成了生产时调用者只需使用类,而不用关心创建类的功能。

  下一篇,我们了解一下在Spring中,对象是如何注入的。

    

posted @ 2020-02-17 14:47  小新而已  阅读(168)  评论(0编辑  收藏  举报