天天看點

Spring 架構學習(一)——IOC思想原型及實質

文章目錄

  • ​​Spring 架構學習(一)——IOC思想原型及實質​​
  • ​​一、我們以前寫業務代碼的方式​​
  • ​​二、使用者更改需求,代碼如何改動​​
  • ​​三、IOC 思想原型​​
  • ​​四、控制反轉​​
  • ​​五、IOC實質​​

Spring 架構學習(一)——IOC思想原型及實質

一、我們以前寫業務代碼的方式

1.UserDao 資料通路接口

package com.kuang.dao;

import java.util.List;
public interface UserDao {
    void selectAll();
}      

2.UserDaoImpl Dao層實作類

package com.kuang.dao;

public class UserDaoImpl implements UserDao{
    public void selectAll() {
        System.out.println("擷取了使用者的資料!");
    }
}      

3.UserService 業務接口

package com.kuang.service;

public interface UserService {
    void getUser();
}      

4.UserServiceImpl 業務實作類

package com.kuang.service;
import com.kuang.dao.UserDao;
import com.kuang.dao.UserDaoImpl;

public class UserServiceImpl implements UserService {
    // 以前這個new Dao層實體類的代碼都寫到方法裡面,也可以寫到外面避免多次建立執行個體
    // 這裡用到了 組合的方式
    
    private UserDao userDao = new UserDaoImpl();

    // 使用者實際調用的是業務層,而不是Dao層
    // 業務層就做一個事情,調Dao層進行使用功能

    public void getUser() {
          userDao.selectAll();
    }

}      

5.測試類 使用者使用業務功能

package com.kuang.test;
import com.kuang.service.UserService;
import com.kuang.service.UserServiceImpl;

public class Test {

 @org.junit.Test
    public void test(){
     UserService userService = new UserServiceImpl();
     userService.getUser();
    }
}      

接口與具體實作類的分開有效的實作了解耦合,但是還不夠友善。

舉幾個例子,來說明Sring為什麼要使用IOC來實作控制反轉,以及什麼是控制反轉

二、使用者更改需求,代碼如何改動

如果使用者增加了一個使用Mysql擷取使用者資料的需求,在上述的方式下我們會怎麼改呢?

1.建立一個其他的類實作UserDao接口,重寫方法的具體代碼

package com.kuang.dao;

public class UserDaoMySQLImpl implements UserDao{
    public void selectAll() {
        System.out.println("MySQL擷取使用者資料!");
    }
}      

2.在UserServiceImpl 業務層具體實作的方法裡面修改代碼,使得UserDao的實作類更改成上面寫的這個新的類

package com.kuang.service;
import com.kuang.dao.UserDao;
import com.kuang.dao.UserDaoMySQLImpl;

public class UserServiceImpl implements UserService {
    // 将接口實作的類 修改了
    private UserDao userDao = new UserDaoMySQLImpl();
    
    public void getUser() {
          userDao.selectAll();
    }
}      

3.測試具體業務功能。

以上面這個例子可以說明一個問題:

  上面的例子中,每次使用者更改需求,我們都要在原代碼的基礎上進行修改,比如使用者想要Orcale擷取資料就要修改成new Orcale,想要SqlServer 擷取使用者資料,就要修改成 new SqlServer。

  這個例子中修改的代碼還不是很多,如果真實的項目中,代碼量成千上萬行,有幾十個類,使用者的需求增加或者更改,那麼就需要在很多地方修改代碼,非常麻煩,開發的效率很低

上述的方式寫代碼,适應不了使用者的需求變更,使用者需求變了,要立馬修改原代碼,非常不好。

是以就有了另外一種寫代碼的具體方式

三、IOC 思想原型

在業務具體實作類這裡,變更寫代碼的方式

package com.kuang.service;
import com.kuang.dao.UserDao;

public class UserServiceImpl implements UserService {
    // 對屬性不做具體的new,交給set接口來設定,控制權直接翻轉
    private UserDao userDao;

    // 使用set的方式實作了值的動态注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUser() {
          userDao.selectAll();
    }
}      

之前的方式是程式控制建立對象(通過new的方式定死了具體的實作對象)

現在是使用者在使用不同需求時,通過set注入自己需要的對象即可實作需求。

package com.kuang.test;
import com.kuang.dao.UserDaoMySQLImpl;
import com.kuang.service.UserService;
import com.kuang.service.UserServiceImpl;

public class Test {

 @org.junit.Test
    public void test(){
     UserService userService = new UserServiceImpl();

     // 加了這一行代碼,使用者實作set注入自己的需要具體對象,不需要修改源代碼中的任意一行
     ((UserServiceImpl)userService).setUserDao(new UserDaoMySQLImpl());
     
     userService.getUser();
    }
}      

  在之前的業務中,使用者的需求可能會影響到我們之前寫的代碼,我們需要根據使用者的需求去修改原代碼。如果程式的代碼量非常大,修改一次的成本非常大。

使用set接口實作,已經發生了革命性的變化(控制反轉)

四、控制反轉

  • 之前程式是主動建立對象的,控制權在程式員手上,是以使用者的每一個需求都會讓我們改代碼。

(程式員用過new來寫死一個建立的對象)

  • 使用set接口,程式不在具有主動性了,而是變成了被動的接收對象。

(使用set接口,原有的程式不用改變,使用者隻需要在使用的時候set一個需要的對象即可)

  當使用者的需求再次增加,我們隻需要擴充一個類來實作之前的接口,寫具體的業務代碼,使用者在使用的時候set注入擴充的類即可。使得程式擴充更加友善,大大降低了系統的耦合性,也使得程式員可以更加專注的寫業務代碼,不需要管理對象的建立了。

  以上就是IOC思想的原型,Spring的IOC底層使用了大量的set方法實作各種對象注入,來解決以上的問題。

五、IOC實質

控制反轉IOC(Inversion of Control)是一種設計思想,DI(依賴注入)是實作IOC的一種具體方式。

上面的例子就是說明了程式中獲得依賴對象的方式反轉了。之前面向對象程式設計中,對象的建立與對象之間的依賴關系完全的寫死在程式中,對象的建立由程式員自己控制,控制反轉後将對象的建立交給第三方容器來做。

Spring 架構學習(一)——IOC思想原型及實質

早些年,各個對象之間都是耦合的,一層調一層,理想的是中間加一個中間件使得各個對象耦合降低,IOC就是降低各個對象耦合度的中間容器。

Spring 架構學習(一)——IOC思想原型及實質