天天看點

Spring控制反轉的了解-IOC的了解

我們通過舉一個小小的例子來說明什麼是控制反轉IOC?

初級階段,我們寫代碼是這樣的:

  1. 建立一個UserDao和它的實作類
public interface UserDao {
    void save();
}
           
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("UserDao.save");
    }
}
           
  1. 建立UserService接口,和它的實作類,調用UserDao,實作相應的業務
public interface UserService {
    void addUser();
}
           
public class UserServiceImpl implements UserService {
    //代碼初級階段,我們都是直接new一個UserDao實作類,然後調用它
    private UserDao userDao = new UserDaoImpl();

    public void addUser() {
        System.out.println("UserServiceImpl.addUser");
        userDao.save();
    }
}
           

初級階段我們這樣寫代碼會有一個嚴重的弊端!!!

  • Service層和Dao層的耦合性太高
  • 如果我們在增加其他的UserDao實作類,比如采用MySQL存儲的MysqlUserDaoImpl,或者采用Oracle存儲的UserDao實作類,就需要更改代碼,這樣做顯然不切實際,我們總不能換一個UserDao實作類,就改一次代碼
  • 什麼叫耦合性?就是,我們在UserServiceImpl中直接new了一個具體的UserDao實作類,這時Service層和這個具體的UserDao關聯了,如果這個UserDao被廢用,整個代碼就不能繼續運作,需要重新更改代碼;

下面我們增加一個MySqlUserDaoImpl:

public class MySqlUserDaoImpl implements UserDao {
    public void save() {
        System.out.println("MySqlUserDaoImpl.save:采用mysql實作資料庫存儲");
    }
}
           
  • 這樣我們就要更改我們的Service層代碼,new一個新的實作類
public class UserServiceImpl implements UserService {
    private UserDao userDao = new MySqlUserDaoImpl();

    public void addUser() {
        System.out.println("UserServiceImpl.addUser");
        userDao.save();
    }
}

           

注意:重點!!

  • 這時,我們将建立userDao的權利交給了程式,在運作的時候,由程式來建立userDao,而不受我們程式員的控制(就是我們想建立哪個UserDao,就建立哪個)

下面我們給UserService向外提供一個接口,實作程式員控制UserDao的建立:

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    //我們通過增加一個set方法,使用者可以傳遞一個userDao進來,然後指派給UserDao
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser() {
        System.out.println("UserServiceImpl.addUser");
        userDao.save();
    }
}
           

像這種通過set方法給UserDao指派的過程就叫依賴注入DI

測試

@Test
public void test1() {
    UserService userService = new UserServiceImpl();
    userService.setUserDao(new MySqlUserDaoImpl());
    userService.addUser();
}
           

或許你還會感覺,這樣還是由程式來建立具體的UserDao,确實上面的代碼,還是受到程式控制

這樣我們給它加一個switch判斷,就更明顯了

@Test
public void test1() {
    UserService userService = new UserServiceImpl();
    int i = 1;
    switch (i){
        case 0:
            userService.setUserDao(new UserDaoImpl());
            break;
        case 1:
            userService.setUserDao(new MySqlUserDaoImpl());
            break;
    }
    userService.addUser();
}
           

這時我們就可以通過鍵盤輸入,來控制對象的建立

這樣的話,我們就可以實作由程式員(使用者)來建立具體的UserDao實作類

  • 這樣的,将建立對象的權利交給使用者,而不是程式的過程就叫控制反轉(IOC);
  • 控制反轉的關鍵在于,我們在代碼中不直接執行個體化具體的對象,而是在運作期間交由使用者動态産生;向外提供接口,供外部傳遞參數;也可以通過動态代理的方法實作

而控制反轉的核心就是依賴注入,什麼是依賴?

  • 上面我們建立UserService的時候,需要調用UserDao的功能,這時UserService就依賴了UserDao
  • 而Spring之是以能夠實作控制反轉,就是因為實作了依賴注入
  • 依賴注入:即我們上面說的,在UserService裡不直接實作一個具體的UserDao,而是通過set方法将UserDao這個依賴動态的注入到UserSvice中

以上就是我對控制反轉IOC的了解