IOC概念
IOC全稱Inversion Of Control,即控制反轉,它不是一項技術,而是面向對象編程中的一種設計原則(思想),可以用來降低我們計算機程序代碼之間的耦合度,提高優化軟件程序設計。它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。也就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。
更通俗的講,傳統的應用程序都是由程序猿同胞們在類內部主動創建對象並實例化,相當於我們的肚子餓了,要自己點外賣來填飽肚子(注入依賴對象)。有了IOC容器,相當於我們找了個女朋友,當我們肚子餓了,由女朋友給我們做飯填飽我們的肚子。女朋友是IOC容器,食物就是依賴對象。我們可以把創建和查找依賴對象的控制權交給容器,由容器注入依賴對象(即實例化對象),這樣不僅大大地減少了程序猿的重複工作量,更降低了程序類與類之間的耦合度,提高了程序代碼的複用性,使得設計的程序結構體系更加靈活,擴展性更強。
理解IOC,我們要從思想上發生根本性的轉變,即主從變化。由原有的程序主動創建並獲取依賴對象,到轉變爲由容器來給到我們一個對象。作爲一個程序猿,不應該關心一個對象的產生,而應該交由容器去創建。這樣當對象的創建方式改變,對我們程序也不會有影響。以上就是我個人理解的IOC的精髓。
IOC的實現方式
IOC有多種實現方式,其中最常見的叫做“依賴注入”(Dependency Injection,簡稱DI),另外還有“依賴查找”(Dependency Lookup)和“依賴拖拽”(Dependency Pull)。
什麼是依賴?看下面代碼就能夠理解:IndexServiceImpl類中有個對象屬性IndexDao,也就是說IndexServiceImpl依賴IndexDao。
package com.tyyd.service.impl;
import com.tyyd.dao.IndexDao;
import com.tyyd.service.IndexService;
/**
* 測試Sercice實現類
*/
public class IndexServiceImpl implements IndexService {
private IndexDao indexDao;
}
依賴注入(Dependency Injection)
組件不做定位查詢,只提供常規的Java方法讓容器去決定依賴關係,Spring中依賴注入由三種方式:接口注入(Interface Injection),設值注入(Setter Injection)和構造方法注入(Constructor Injection)三種方式,其中接口注入由於在靈活性和易用性比較差,現在從Spring4開始已被廢棄。
接口注入代碼:
package com.tyyd.dao;
/**
* DAO接口
*/
public interface IndexDao {
void createIndexDao(IndexDao indexDao);
}
package com.tyyd.service.impl;
import com.tyyd.dao.IndexDao;
import com.tyyd.service.IndexService;
/**
* 測試Sercice實現類
*/
public class IndexServiceImpl implements IndexService, IndexDao {
private IndexDao indexDao;
/**
* 測試方法
*/
public void test() {
indexDao.test();
}
public void createIndexDao(IndexDao indexDao) {
this.indexDao = indexDao
}
}
設置注入代碼:
package com.tyyd.service.impl;
import com.tyyd.dao.IndexDao;
import com.tyyd.service.IndexService;
/**
* 測試Sercice實現類
*/
public class IndexServiceImpl implements IndexService {
private IndexDao indexDao;
/**
* 測試方法
*/
public void test() {
indexDao.test();
}
/**
* IOC Set方法注入
* @param indexDao
*/
public void setIndexDao(IndexDao indexDao) {
this.indexDao = indexDao;
}
}
構造方法注入代碼:
package com.tyyd.service.impl;
import com.tyyd.dao.IndexDao;
import com.tyyd.service.IndexService;
/**
* 測試Sercice實現類
*/
public class IndexServiceImpl implements IndexService {
@Autowired
private IndexDao indexDao;
/**
* IOC 構造方法注入
* @param indexDao
*/
public IndexServiceImpl(IndexDao indexDao) {
this.indexDao = indexDao;
}
/**
* 測試方法
*/
public void test() {
indexDao.test();
}
}
依賴查找(Dependency Lookup)
public class PigServiceImpl {
private DataSource dataSource;
private PigDao pigDao;
public PigServiceImpl(){
Context context = null;
try{
context = new InitialContext();
dataSource = (DataSource)context.lookup(“java:comp/env/dataSourceName”);
pigDao = (PigDao) context.lookup(“java:comp/env/PigDaoName”);
} catch (Exception e) {
}
}
}
依賴拖拽(Dependency Pull)
即注入的對象如何與組件發生聯繫,這個過程就是通過依賴拖拽實現。
代碼示例:
package com.tyyd.ioc.test;
import com.tyyd.ioc.annotation.service.impl.PigServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:spring-ioc.xml");
PigServiceImpl pigService = (PigServiceImpl)classPathXmlApplicationContext.getBean("pigServiceImpl");
pigService.test();
}
}
通常我們對注入對象的配置可以通過一個xml文件完成。並使用這種方式對對象進行集中管理,使用依賴拖拽與依賴查找本質的區別是,依賴查找是在業務組件代碼中進行的,而不是從一個集中的註冊處,特定的地點執行。