Spring IoC有什么好处呢?

https://www.zhihu.com/question/23277575


作者:David
链接:https://www.zhihu.com/question/23277575/answer/121015545
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

有个土豪老板,我们经常要出差,因此经常要订机票。定机票呢,可以通过去哪儿网订票,也可以通过携程订票。

我们马上可以想到可以通过三个类来表达这个场景,Boss,QunarBookingService,CtripBookingService。当然了,我们还应该提供一个BookingService接口,作为QunarBookingService,CtripBookingService的公共抽象。面向接口编程是面向对象设计的基本原则,如果这都不了解,赶紧先回去看GoF的《设计模式》第一章!

BookingService.java

package com.tianmaying.iocdemo;

public interface BookingService {
    void bookFlight();
}

QunarBookingService.java

package com.tianmaying.iocdemo;

public class QunarBookingService implements BookingService {
    public void bookFlight() {
        System.out.println("book fight by Qunar!");

    }
}

CtripBookingService.java

package com.tianmaying.iocdemo;

public class CtripBookingService implements BookingService {
    public void bookFlight() {
        System.out.println("book fight by Ctrip!");
    }
}

好了,土豪出门谈生意,得订机票了,Boss就琢磨着怎么订票呢,Boss比较了一下价格,这一次决定用去哪儿,对应的Boss的代码:

Boss.java

package com.tianmaying.iocdemo;

public class Boss {

    private BookingService bookingService;

    public Boss() {
        this.bookingService = new QunarBookingService();
    }

    public BookingService getBookingService() {
        return bookingService;
    }

    public void setBookingService(BookingService bookingService) {
        this.bookingService = bookingService;
    }

    public void goSomewhere() {
        bookingService.bookFlight();
    }
}

在Boss的构造函数中,将其bookingService成员变量实例化为​QunarBookingService,goSomewhere()函数中就可以调用bookingService的bookFlight方法了!

为了把这个场景Run起来,我们还需要一个main函数:

package com.tianmaying.iocdemo;

public class App {
    public static void main(String[] args) {
        bossGoSomewhere();
    }

    static void bossGoSomewhere() {
        Boss boss = new Boss();
        boss.goSomewhere();
    }
}

运行之后可以看到控制中可以打印出"book fight by Qunar!"了。


使用IoC的场景

在这个例子中,我们看到Boss需要使用BookingService,于是Boss自己实例化了一个QunarBookingService对象。同志们想想,身为土豪Boss,思考的都是公司战略的事儿,定个票还要自己选择通过什么方式来完成,这个Boss是不是当得实在太苦逼。


所以土豪赶紧给自己找了个美女秘书(别想歪!),Boss要出差时,只需要说一声他需要订票服务,至于是哪个服务,让美女秘书选好后告诉他即可(注入啊!注入!)。(别跟我较真说美女秘书直接把票送上就行!)


这样的话,Boss是不是一身轻松了? 而这个美女秘书还是免费包邮的,这正是Spring扮演的角色!来看看使用Spring之后的代码。


我们在pom.xml文件中加入依赖(项目使用Maven作为构建工具):

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.0.RELEASE</version>
</dependency>

QunarBookingService.java

package com.tianmaying.iocdemo;
import org.springframework.stereotype.Component;

@Component
public class QunarBookingService implements BookingService {
    public void bookFlight() {
        System.out.println("book fight by Qunar!");

    }
}

这里我们使用Spring的@Component标注将QunarBookingService注册进Spring的Context,这样它就可以被注入到需要它的地方!相应地,创建QunarBookingService实例的责任也交给了Spring。我们说了,美女秘书帮你搞定嘛!


新建一个SmartBoss类,聪明的老板知道把选择订机票服务这样的杂事交给秘书来做。

SmartBoss.java

package com.tianmaying.iocdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SmartBoss {
    private BookingService bookingService;

    @Autowired
    public void setBookingService(BookingService bookingService) {
        this.bookingService = bookingService;
    }

    public BookingService getBookingService() {
        return bookingService;
    }

    public void goSomewhere() {
        bookingService.bookFlight();
    }
}

在上面的代码中,SmartBoss不再自己创建BookingService的实例,只是通过@Autowired标注告诉Spring小秘我需要一个BookingService!


调用代码因此也要做一些小修改,需要创建Spring的Context:

static void smartBossGoSomewhere() {
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(
            App.class);
    try {
        SmartBoss boss = context.getBean(SmartBoss.class);
        boss.goSomewhere();
    } finally {
        context.close();
    }
}


IoC的好处


回到正题,通过上面的例子,我们来看看IoC到底带来了哪些好处?


Boss没有和某个具体的BookingService类耦合到一起了,这样Boss的维护和演化就更加方便。想象一下,如果Boss需要改用CtripBookingService,这时也不需要修改Boss.java的代码,更换接口的实现非常方便,给Boss注入新的实现即可,轻松惬意。(当然,要做到热插拔还需要进一步的工作,要么得玩转类加载器这玩意,或者借助OSGi这样的神器)。这也是典型的开放-封闭原则的例子,即对现有模块,功能扩展应该是开放的,而对其代码修改应该是封闭的,即能够做到不需要修改已有代码来扩展新的功能。


想象一下,如果Boss自己直接去实例化QunarBookingService,而QunarBookingService在另外一个Package中甚至另外一个Jar包中,你可得import进来才能使用,紧耦合啊!现在好了,Boss只依赖于抽象接口,测试更方便了吧,Mock一下就轻松搞定!Boss和QunarBookingService彼此不知道对方,Spring帮两者粘合在一起。


为什么IoC是个大招,因为它会自然而然得促进你应用一些好的设计原则,会帮助你开发出更加“高内聚低耦合”的软件。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值