我理解的IOC技術在Java和C#中比較分析
一直想用心寫這個系列的文章,其實看得越多,也就越覺得自己在這方面的功力太淺,也就越不想班門弄斧啦,作為一個開篇,我想把這個技術深層次化,在之前的.net的一個MVC系列文章其實已經涉及到了,只是.net在這方面的應用不如java來得這麼猛烈,這麼酣汗淋漓,所以也就下定決心,這一階段針對這一個技術點進行深層次的剖析。
IOC,英文全稱Inversion of Control,中文直譯控制反轉,一般我們稱之為“依賴注入”原則,在我還未過多涉足java領域時,在C#語言24個設計模式中(參見《大話設計模式》)有一個依賴倒轉原則,作為一個設計模式的原則而不是一個模式。在接觸java之後,尤其是spring框架後,被稱之為“依賴注入”IOC設計模式。其實大體的意思和意義都是差不多的,只是在我看來,在C#領域對這個技術的應用沒有那麼廣泛,限於.NET技術的先天性,我很少看到這方面的鉅作,也許是我太膚淺。在我上次寫基於.NET的MVC ProDinner系列文章時候,查詢這方面的文章,幾乎是為零,只能自己去看MVC原始碼或者Castle 專案原始碼。
首先看看《大話設計模式》中基於C#語言如何詮釋這門藝術的。原著由維修計算機入題,在我們日常生活中,我們很自然地,提高計算機速度需要更高的CPU,需要更快的系統響應度就需要更好的記憶體,需要更大的儲存介質,就需要擴大硬碟,在這一系列的活動中,於是我們就自然而然的發現,計算機速度依賴CPU,在CPU的使用中我們從來不關心CPU是怎麼設計出來的,我們只需要關注這是Intel還是AMD的CPU,因為他決定了你的主機板型別,當確定了CPU之後,我們只需關注你需要使用那款CPU,因為介面主機板都是一樣的,也即是說,大的功能不會去關注具體每一款產品的實現,而只需要關注產品與產品之間的標準化介面。由此引出來這個原則的定義:
A、高層模組不應該依賴低層模組,兩個都應該依賴抽象
B、抽象不應該依賴細節,細節應該依賴抽象
這麼講其實是比較抽象的,具體到程式碼中實際上就是,層於層之間,各模組間,各專案間都應該使用介面層來完成模組的融合。 當某個角色(可能是一個物件例項,呼叫者)需要另一個角色(另一個物件例項,被呼叫者)的協助時,在傳統的程式設計過程中,通常由呼叫者來建立被呼叫者的例項。而控制反轉中建立被呼叫者的工作不再由呼叫者來完成。建立被呼叫者 例項的工作通常由特定的容器來完成,然後注入呼叫者,因此也稱為依賴注入。
廢話不多說,理論講得再精彩最終看程式碼實現,依據我對這些該概念的理解,我們一起看基於C#語言寫出的例項:
需求場景:
父親在完成一件事情的時候,由於各方面原因需要自己的子女幫忙才能完成,所以,父親需要去調動自己的兒子或者女兒才能完成這件事情
型別設計:
介面 Iperson為被呼叫者的基型別
類 Father 呼叫者
類 Son 被呼叫者
類 Daughter 被呼叫者
類 Container 依賴注入容器
程式分析:
Father類通過呼叫抽象層介面,來完成這個操作,至於呼叫兒子還是女兒我們在建構函式中完成型別的選擇。也就是說Father是呼叫者,Son和Daughter是被呼叫者,Container是依賴注入的生成容器。負責將呼叫者Son或者Daughter物件例項化給呼叫者。
.NET 程式目錄結構:
開啟visual studio 建立控制檯應用程式,介面層程式碼實現:
1 //介面層 2 public interface Iperson 3 { 4 void operation(); 5 }
呼叫者程式碼實現:
1 //呼叫者實現類 2 public class Father 3 { 4 Iperson iperson; 5 6 Container container = new Container(); 7 8 public Father(String typeName) 9 { 10 iperson = container.GetApplication(typeName); 11 } 12 public void operation() 13 { 14 iperson.operation(); 15 } 16 }
Container 在這裡我直接new出例項了,看到這個程式碼熟悉java spring框架的同學就似曾相識了,一般是用@autowired來修飾依賴注入的操作控制程式碼。Father類中的operation方法並沒有自己去實現任何操作,而是呼叫了iperson的操作來實現自己的方法,而iperson只是一個介面型別,需要具體的實現類,程式碼才能執行起來,我們看iperson的兩個實現層:
//被呼叫者類 ipseron實現層 public class Son:Iperson { public void operation() { Console.WriteLine("son is the operator"); } } //被呼叫者之二 public class Daughter:Iperson { public void operation() { Console.WriteLine("daughter is the operator"); } }
Conatiner是實現容器,原理其實很簡單,反射技術,反射原理進行不同的封裝其實就形成了不同的技術框架,java spring的ioc核心離不開反射,許多的資料庫mapper框架同樣也離不開反射,看看程式碼實現:
//生成例項容器 public class Container { public Iperson GetApplication(String typeName) { return (Iperson) Activator.CreateInstance(Type.GetType(typeName)); } }
當然,我這是最基本的反射實現了,在生成化產品化的框架中反射遠沒有這麼簡單,但原理都是相同的。好,看下測試類實現程式碼:
class Program { static void Main(string[] args) { //呼叫son Father fa = new Father("IOCblog.Son"); fa.operation(); //呼叫daughter fa = new Father("IOCblog.Daughter"); fa.operation(); } }
程式執行結果:
程式碼寫到這裡對這個概念有所掌握的同學,其實會是有共鳴的,這是依賴注入最基本的實現了,日常專案開發中基於框架級別來實現這種模式思想,我們很多時候是用修飾符或者配置檔案,典型的就是java下面的spring的實現。java spring框架可沒那麼簡單,spring兩大核心ioc和aop,實現的手段無非也是如此,但不同的是思想!思想!我這裡如若再用java套spring框架來做示例實現java下的IOC的思想,肯定也就沒人有興趣繼續看下去了,這篇文章的含金量就沒那麼誘人啦,那麼我們來高階點的:
基於java程式碼的模擬spring框架IOC實現
實現java下的ioc毫無疑問,我們首先專業術語就換成了,我們需要JavaBean來實現注入,需要factory來實現容器,實現步奏:
1、建立需要實現注入的JavaBean,注入類Person和容器類Persons
2、建立類似spring框架的application.xml配置檔案,將依賴的JavaBean和相應注入的屬性配置在xml檔案中,我們這裡取名叫 IocApplication.xml
3、實現注入容器的factory類,主要負責讀配置檔案->依據配置檔案進行物件例項化->放入persons map集合當中,以備呼叫。
java程式目錄結構:
大體實現思路如上所述,好,廢話不多說,看看程式碼如何實現,第一步和第二步程式碼如下(切換到eclipse下,建立java應用程式):
package com.ioc.bean; //被呼叫注入類 public class Person { private String name; public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
package com.ioc.bean; //beans類 public class Persons { private Person son; public Person getSon() { return this.son; } public void setSon(Person son) { this.son = son; } private Person daughter; public Person getDaughter() { return this.daughter; } public void setDaughter(Person daughter) { this.daughter = daughter; } }
實現的容器factory程式碼量比較大,這裡就不依依貼出,所有的原始碼都在附件中可自由下載,這裡主要分析幾個關鍵步奏:
實現容器,主要負責一件事件,通過配置的xml,對相應的javabean進行反射,生成例項化物件,存入map中,xml配置實現:
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="son" class="com.ioc.bean.Person"> <property name="name"> <value>mark</value> </property> </bean> <bean id="daughter" class="com.ioc.bean.Person"> <property name="name"> <value>cindy</value> </property> </bean> <bean id="father" class="com.ioc.bean.Persons"> <property name="son"> <ref bean="son" /> </property> <property name="daughter"> <ref bean="daughter" /> </property> </bean> </beans>
容器實現map操作程式碼:
private Map<String,Object> beanMap=new HashMap<String,Object>(); /** * 初始化xml檔案 * */ public void init(String xmlUrl){ SAXReader saxReader=new SAXReader(); File file=new File(xmlUrl); try{ saxReader.addHandler("/beans/bean",new BeanHandler()); saxReader.read(file); } catch(DocumentException e){ System.out.println(e.getMessage()); } } /** * 根據beanid來獲取bean * */ public Object getBean(String beanId){ Object obj=null; obj=beanMap.get(beanId); return obj; }
BeanHandler毫無疑問就是具體去操作IocApplication.xml檔案的操作類,程式碼比較長,可以下載附件原始碼檢視。
好,看下測試類程式碼:
package com.ioc.test; import com.ioc.bean.Person; import com.ioc.factory.BeanFactory; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub String xmlUrl="src/IocApplication.xml"; BeanFactory factory=new BeanFactory(); factory.init(xmlUrl); Person me=(Person)factory.getBean("son"); System.out.println("Son's name:"+me.getName()); } }
程式執行結果:
java 模擬spring實現,可以參考這篇文章:http://only1.iteye.com/blog/733550
結束語:
這篇文章我們暫且不來比較依賴注入和反轉的區別,依賴反轉和依賴注入很多程式設計師把這兩個概念當成一個理解,認為只是不同的解釋,其實細分還是有區別的
1、依賴注入是從應用程式的角度在描述,也就是說,應用程式依賴容器建立並注入它所需要的外部資源;而控制反轉是從容器的角度在描述,容器控制應用程式,由容器反向的嚮應用程式注入應用程式所需要的外部資源。
2、IOC,控制反轉是軟體執行時體現出來的一個特徵:如果物件A執行時依賴於物件B,但A並不去建立B,而是從外界直接取得B。也就是說,一個物件並不是自己去建立它所依賴的其它物件。DI,依賴注入是控制反轉的一種實現手段。如上面的例子,B的取得並不需要A的干涉,而是利用某些框架在通過構造引數或屬性設定來實現。
關於這些這裡就不展開敘述,後面我們再詳細討論,這節主要討論依賴注入,我們首先在這節暫時認為這是一個相同的概念。作為概述,首先我們瞭解下IOC概念,再看看java和C#在這一概念上的運用比較。
最後附上我的原始碼
Java程式碼 http://files.cnblogs.com/aspnetdream/iocblog.rar
C#程式碼 http://files.cnblogs.com/aspnetdream/Csharp_IOCblog.rar
相關文章
- Java 中比較 BigDecimal 的陷阱JavaDecimal
- java8-Lambda中比較器Comparator的使用Java
- 較好的JAVA技術網Java
- 機器學習中比較重要的幾個概念機器學習
- 談談我對Spring IOC的理解Spring
- http協議中比較重要的幾個頭HTTP協議
- java web技術比較好的spring和hibernate書籍JavaWebSpring
- Spring(二):IOC和DI的理解Spring
- Bigo的Java面試,我掛在了第三輪技術面上.........GoJava面試
- 淘寶,京東,蘇寧易購技術架構(路線)分析和比較架構
- 如何理解Spring中的IOC和AOPSpring
- IOC理解
- 分析技術在PMP中的應用
- 關於iOS開發中比較常見的優化iOS優化
- C#中的依賴注入和IoC容器C#依賴注入
- C# Java之比較 (轉)C#Java
- 如何在RFT中比較兩個影像檔案?
- PHP中比較兩個時間的大小與日期的差值PHP
- 深入理解Spring IOC原始碼分析Spring原始碼
- 跨鏈技術的分析和思考
- 由淺入深理解 IOC 和 DI
- 我理解的 Java 泛型Java泛型
- 我的JAVA運算子理解Java
- 我如何理解Java中抽象類和介面Java抽象
- 我的技術心病
- RFID技術在人員定位和監控方面相較於其他技術有何明顯優勢?
- 面試題分析:我的Twitter技術面試失敗了面試題
- C#和Java,究竟選哪個方向?我只說事實,你自己分析……C#Java
- 索引的分析和比較索引
- 「我在淘天做技術」雙11背後的營銷技術體系
- 我在 Google 做技術經理的一天Go
- pl/sql中比較好玩的一種連結資料庫方式SQL資料庫
- IOC技術在前端專案中的應用前端
- 技術支援在大資料分析中的作用大資料
- 情感分析技術在美團的探索與應用
- 如何理解 Laravel 的 IoC 容器Laravel
- 我在 ONES 等你 | 寶藏公司技術招聘
- IOC注入技術之編譯時注入編譯