为何要使用Spring IOC?

思考

Spring已经占据咱们Java开发框架中的半壁江山了,从一开始工做咱们就在使用Spring。可是到底为何要用Spring,可能不少人都没有去思考过这个问题?许多人可能也疲于应对需求,无暇思考这种看似理所固然的问题。那今天,咱们就好好来讨论一下究竟为何要使用Spring IOC?html

逆向思考

假设在最初没有Spring IOC这种框架的时候,咱们采用传统MVC的方式来开发一段常见的用户逻辑。mysql

用户DAO程序员

public class UserDAO {

    private String database;

    public UserDAO(String dataBase) {
        this.database = dataBase;
    }
    public void doSomething() {
        System.out.println("保存用户!");
    }

}

用户Servicespring

public class UserService {

    private UserDAO dao;

    public UserService(UserDAO dao) {
        this.dao = dao;
    }
    public void doSomething() {
        dao.doSomething();
    }

}

用户Controllersql

public class Controller {

    public UserService service;

    public Controller(UserService userService) {
        this.service = userService;
    }

    public void doSomething() {
        service.doSomething();
    }

}

接下来咱们就必须手动一个一个建立对象,并将dao、service、controller依次组装起来,而后才能调用。数据库

public static void main(String[] args) {

        UserDAO dao = new UserDAO("mysql");
        UserService service = new UserService(dao);
        Controller controller = new Controller(service);

        controller.doSomething();

    }

分析一下这种作法的弊端有哪些呢?编程

  1. 在生成Controller的地方咱们都必须先建立dao再建立service最后再建立Controller,这么一条繁琐的建立过程。
  2. 在这三层结构当中,上层都须要知道下层是如何建立的,上层必须本身建立下层,这样就造成了紧密耦合。为何业务程序员在写业务的时候却须要知道数据库的密码并本身建立dao呢?不只如此,当若是dao的数据库密码变化了,在每一处生成Controller的地方都须要进行修改。
  3. 经过new关键字生成了具体的对象,这是一种硬编码的方式,违反了面向接口编程的原则。当有一天咱们从Hibernate更换到Mybatis的时候,在每一处new DAO的地方,咱们都须要进行更换。
  4. 咱们频繁的建立对象,浪费了资源。

这时候咱们再来看看若是用SpringIOC的状况,刚才的代码变成以下。app

public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        Controller controller = (Controller) context.getBean("controller");
        controller.doSomething();
        
    }

很明显,使用IOC以后,咱们只管向容器索取所需的Bean便可。IOC便解决了如下的痛点:框架

  1. Bean之间的解耦,这种解耦体如今咱们没有在代码中去硬编码bean之间的依赖。(不经过new操做依次构建对象,由springIOC内部帮助咱们实现了依赖注入)。一方面,IOC容器将经过new对象设置依赖的方式转变为运行期动态的进行设置依赖。
  2. IOC容器自然地给咱们提供了单例。
  3. 当须要更换dao的时候,咱们只须要在配置文件中更换dao的实现类,彻底不会破坏到以前的代码。
  4. 上层如今不须要知道下层是如何建立的。

经过这个例子可能读者有点如有所思了,那咱们再来看一下IOC的定义是什么。组件化

定义

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,能够用来减低计算机代码之间的耦合度。其中最多见的方式叫作依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。经过控制反转,对象在被建立的时候,由一个调控系统内全部对象的外界实体将其所依赖的对象的引用传递给它。也能够说,依赖被注入到对象中。

解读

控制反转,控制体如今什么地方?控制就体如今咱们一开始的例子,上层须要去控制new下层对象。而反转意味着什么呢?
反转意味着咱们把对象建立的控制权交出去,交给谁呢?交给IOC容器,由IOC容器负责建立特定对象,并填充到各个声明须要特定对象的地方。同窗们可能会对IOC和DI以为很绕,其实IOC至关于接口,它规定了要实现什么?而依赖注入(DI)就是具体的实现,它实现了IOC想要的效果。IOC的思想很好地体现了面向对象设计法则之一——好莱坞法则:“别找咱们,咱们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

如何减低耦合?咱们举个例子,当在IDEA开发环境中咱们添加插件的时候,却须要去知道该插件须要什么依赖,要怎么才能成功开启插件?是否是对用户至关不友好呢?既然咱们要使用插件,意味着咱们和插件之间是耦合的,没法避免。可是若是咱们还须要知道插件须要的依赖和开启插件的步骤,说明咱们和插件之间的耦合关系更强烈了。因此SpringIOC的定义当中写道“下降耦合”而非“消除耦合”,但只要耦合度下降的话,就有利于代码的维护和扩展。思考一下?是否是跟Maven的机制很相似呢?在Maven中声明依赖的话,Maven的自动将该依赖所需的其余依赖递归的寻找。你能够把你本身想象成一个对象的设计师,你设计了一张对象内部构造的图纸,交给SpringIOC,它会自动地根据这份图纸生成这个对象。

IOC容器实现了开发中对象粒度的一种组件化,将每一个对象当作组件同样放进容器当中。而每一个组件都是可插拔,这种是最佳的对象解耦方式。一方面经过将对象之间的耦合关系从编译期推迟到运行期。一旦有须要这个对象的话,就直接使用,客户程序员彻底不须要知道这个对象的前因后果。而且IOC容器对Bean的统一管理使得AOP的实现更加的方便。这样一来,咱们客户程序员就能够更专一在业务代码的编写上。

笔者水平有限,但愿这篇文章对读者有帮助。若有错误,烦请你们指出。

转自个人我的博客 vc2x.com

相关文章
相关标签/搜索