学习Spring,IOC是个绕不过来的话题。作为Spring的根底,IOC有太多博客和教程了。这里做个简略的梳理,以找工作为例,谈谈我对IOC的了解。

在经典的MVC架构这,个别会有Dao、Service和Controller层,咱们用Dao和Service举例,我的项目构造如图:

其中WorkerService调用WorkDao的实现,代码如下:

public class WorkerService {    private WorkerDao workerDao = new WorkerDaoImpl();    /**     * 找工作     */    public void findJob(){        workerDao.findJob();    }}

WorkerDaoImpl代码如下:

public class WorkerDaoImpl implements WorkerDao {    /**     * 找工作     */    @Override    public void findJob() {        System.out.println("find job default");    }}

测试代码:

public class WorkerServiceTest {    @Test    public void findJob() {        WorkerService workerService = new WorkerService();        workerService.findJob();    }}

到目前为止没有问题,运行起来看下:

类图如下:

当初问题来了。我想要一个固定类型的工作,比方Java开发的工作。先增加一个对应的实现:

public class JavaWorkerDaoImpl implements WorkerDao {    /**     * 找工作     */    @Override    public void findJob() {        System.out.println("find java worker!");    }}

同样,对应的WorkerService也批改一下:

public class WorkerService {//    private WorkerDao workerDao = new WorkerDaoImpl();    private WorkerDao workerDao = new JavaWorkerDaoImpl();    /**     * 找工作     */    public void findJob(){        workerDao.findJob();    }}

能够看出,此时只须要把WorkerDao的实现改成JavaWorkerDaoImpl类就行了。运行:

同样,如果须要其余的工作,只须要不同的实现就行了。惟一的问题是,须要改变业务代码,来兼容客户端的需要。

接下来开始做一点批改。先把WorkerService做一点革新:

public class WorkerService {//    private WorkerDao workerDao = new WorkerDaoImpl();    private WorkerDao workerDao;    /**     * 找工作     */    public void findJob(){        workerDao.findJob();    }    public WorkerDao getWorkerDao() {        return workerDao;    }    public void setWorkerDao(WorkerDao workerDao) {        this.workerDao = workerDao;    }}

这样客户端的测试代码就成了这样:

public class WorkerServiceTest {    @Test    public void findJob() {        WorkerService workerService = new WorkerService();        WorkerDao workerDao = new WorkerDaoImpl();        workerService.setWorkerDao(workerDao);        workerService.findJob();    }}

这个时候,workderDao实例化时,只须要客户端指定就行了,客户端能够依照本人想要的来set对应的WorkerDao的实现。这样一来,对于客户端的需要变动,业务层不须要做任何批改。
看下此时的类图:

这里有四个角色:WorkerDao及其实现类、WorkerService业务类、Test类(客户端)。以目前这种形式解耦了业务层和客户端,业务类的代码不会依据客户端的需要来扭转。比照下面的图能够看出,业务类WorkerService并不间接治理WorkerDao,业务更内聚。

当初回到IOC。所谓管制反转,就是要把对象的管理权交出去。最开始的实现UserService类须要本人来new WorkerDaoImpl()来实现WorkerDao,这样治理WorkerDao就成了WorkerService来做的了。后续的实现则是把WorkerDao的实现交给客户端来实现,把控制权交给了客户端。

  • 管制:谁来创建对象,谁就有控制权
  • 反转:对象的创立不再由业务管制,业务类只须要被动地接管客户端set进来的类