我們通過舉一個小小的例子來說明什麼是控制反轉IOC?
初級階段,我們寫代碼是這樣的:
- 建立一個UserDao和它的實作類
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("UserDao.save");
}
}
- 建立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的了解