在開始介紹NHibernate和Spirng.Net以前,有必要先介紹一下相對應的兩個Java開源框架Hibernate和Spring。它們是在Java的Web應用開發中已經很成熟的框架,而前者則是兩個還不成熟的.Net中的開源框架,它們在SourceForge開源社區中正在獲得不斷的補充和完善,其最終目標就是要在.NET環境下實現Hibernate和Spring的所有 特性。
Spring是一個解決了許多在J2EE開發中常見問題的強大框架,它提供了管理業務對象的一致方法而且鼓勵注入對接口編程而不是對類編程的良好習慣。Spring提供了惟一的數據訪問抽象,包括簡單和有效率的JDBC框架,極大改進了效率而且減小了可能的錯誤。Spring的數據訪問架構還集成了Hibernate和其餘O/R mapping解決方案。Spring還提供了惟一的事務管理抽象,它爲各類底層事務管理技術,例如JTA或者JDBC事務提供一個一致的編程模型。Spring提供了一個用標準Java語言編寫的AOP框架,它給POJO提供了聲明式的事務管理和其餘企業事務。這個框架足夠強大,使得應用程序可以拋開EJB的複雜性,同時享受着和傳統EJB相關的關鍵服務。Spring還提供了能夠和IoC容器集成的強大而靈活的MVC Web框架。
Hibernate是一個開放源代碼的對象關係映射(Object-Relation Mapping,ORM)框架,它對JDBC進行了很是輕量級的對象封裝,使得Java程序員能夠爲所欲爲地使用對象編程思惟來操縱數據庫。Hibernate能夠應用在任何使用JDBC的場合,既能夠在Java的客戶端程序使用,也能夠在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate能夠在應用EJB的J2EE架構中取代CMP,完成數據持久化的重任。鑑於Hibernate在Java社區巨大的影響力,它其實已經成爲Java社區的持久層技術事實上的標準。
基於.NET的開發框架NHibernate和Spring.Net分別來源於上述提到的兩個Java框架,框架結構和實現功能都基本一致,只不過應用環境從Java轉到了.NET。到目前爲止NHibernate和Spring.NET仍然處於完善階段,不是特別成熟穩定,可是具備Hibernate和Spring的強大背景,使得它們有着很光明的將來。事實上,如今NHibernate和Spring.NET正在被愈來愈多的開發人員所熟知,而且有些開發人員已經開始嘗試在本身的項目中使用這兩個框架。
1.5.1 企業開發框架的優點
在當今的企業環境中,開發企業應用程序是一個至關繁瑣、浪費時間的過程,爲了讓這個過程變得相對簡單且高效,一些開源的、輕量級的框架正在被普遍的使用,好比Java下的Structs、Spring、Hibernate、iBATIS以及.NET下的Spring.Net和NHibernate等。
它們的普遍使用下降了系統開發的複雜度,弱化了系統各模塊間的耦合程度,縮短了開發週期,加強了系統的可維護性和可擴展性。「站在巨人的肩膀上」是牛頓的一句名言,它已經成爲google學術搜索引擎的座右銘,一樣也爲筆者所推崇。筆者對.Net軟件開發平臺的設想以下,採用開源的ORM框架作數據持久層,ASP.NET沒有合適的Web層框架,採用Asp.Net的Code-behind方式編寫代碼,數據持久層同Web表現層之間的鏈接採用IoC容器。
衡量了多種框架之後,最終筆者推薦採用的技術架構就是NHibernate+Spring.Net+ASP.NET,下面對NHibernate和Spring.net分別進行比較詳細的介紹。
1.5.2 NHibernate介紹
在今日的企業環境中,把面向對象的軟件和關係數據庫一塊兒使用多是至關麻煩和浪費時間的。NHibernate是一個面向.NET環境的對象/關係數據庫映射工具。對象/關係數據庫映射(object/relational mapping,ORM)這個術語表示一種技術,用來把對象模型表示的對象映射到基於SQL的關係模型數據結構中去。
NHibernate不只僅管理.NET類到數據庫表的映射(包括.NET 數據類型到SQL數據類型的映射),還提供數據查詢和獲取數據的方法,能夠大幅度減小開發時人工使用SQL和ADO.NET處理數據的時間。
NHibernate的目標主要是用於與數據持久化相關的編程任務,可以使開發人員從原來枯燥的SQL語句的編寫中解放出來,解放出來的精力可讓開發人員投入到業務邏輯的實現上。對於以數據爲中心的程序,開發人員每每是在數據庫中使用存儲過程來實現商業邏輯,這種狀況下NHibernate可能不是最好的解決方案,但對於那些基於.NET,而且可以實現OO業務模型和商業邏輯的中間層應用,NHibernate是最有用的。NHibernate能夠幫助用戶消除或者包裝那些針對特定廠商的SQL代碼,而且幫用戶把結果集從表格式的表示形式轉換成一系列的對象。
1.NHibernate體系結構
NHibernate體系結構如圖1-51所示。它體現了NHibernate如何使用數據庫和配置文件數據來爲應用程序提供持久化服務(和持久化的對象)。
在NHibernate全面解決體系中,NHibernate運行時體系結構的細節如圖1-52所示。
圖1-51 NHibernate體系結構 圖1-52 NHibernate詳細體系結構
SessionFactory(NHibernate.IsessionFactory):它是Session的工廠,是ConnectionProvider的客戶。能夠持有一個可選的(第二級)數據緩存,能夠在進程級別或集羣級別保存的能夠在事物中重用的數據。
會話(NHibernate.ISession):單線程,生命期較短的對象,表明應用程序和持久化層之間的一次對話。封裝了一個ADO.NET鏈接,也是Transaction的工廠。保存有必需的(第一級)持久化對象的緩存,用於遍歷對象圖,或者經過標識符查找對象。
持久化對象(Persistent)及其集合(Collections):生命期較短的單線程的對象,包含了持久化狀態和商業功能。這些多是普通的對象,惟一特別的是如今從屬於且僅從屬於一個Session。一旦Session被關閉,它們都將從Session中取消聯繫,能夠在任何程序層自由使用(好比,直接做爲傳送到表現層的DTO,數據傳輸對象)。
臨時對象(Transient Object)及其集合(Collection):目前沒有從屬於一個Session的持久化類的實例。這些多是剛剛被程序實例化,尚未來得及被持久化,或者是被一個已經關閉的Session實例化。
事務Transaction (NHibernate.ITransaction):(可選)單線程,生命期較短的對象,應用程序用其來表示一批工做的原子操做,它是底層的ADO.NET事務的抽象。一個Session在某些狀況下可能跨越多個Transaction事務。
ConnectionProvider(NHibernate.Connection.ConnectionProvider):(可選)ADO.NET鏈接的工廠。從底層的IDbConnection抽象而來。對應用程序不可見,但能夠被開發者擴展/實現。
TransactionFactory(net.sf.hibernate.TransactionFactory):(可選)事務實例的工廠。對應用程序不可見,但能夠被開發者擴展/實現。
2.持久化類
持久化類是應用程序用來解決商業問題的類(好比,在電子交易程序中的Customer和Order)。持久化類是暫時存在的,實例會被持久性保存於數據庫中。
若是這些類符合簡單的規則,NHibernate可以工做得最好,這些規則就是Plain Old CLR Object(POCO,簡單傳統CLR對象)編程模型。
POCO簡單示例(用一個類描述一隻貓)以下:
#001 public class Cat
#002 {
#003 private long _id; // 標識符
#004 private string _name; // 名字
#005 private DateTime _birthdate; // 出生日期
#006 private Cat _mate; // 貓的配對
#007 private Set _kittens; // 貓仔
#008 private Color _color; // 顏色
#009 private char _sex; // 性別
#010 private float _weight; // 體重
#011 public long Id // 標識符屬性
#012 { get { return _id; }
#013 set { _id = value; }
#014 public string Name // 名字屬性
#015 { get { return _name; }
#016 set { _name = value; }}
#017 public DateTime Birthdate // 出生日期屬性
#018 { get { return _birthdate; }
#019 set { _birthdate = value; }}
#020 public Cat Mate // 貓的配對屬性
#021 { get { return _mate; }
#022 set { _mate = value; }}
#023 public Set Kittens // 貓仔屬性
#024 { get { return _kittens; }
#025 set { _kittens = value; }}
#026 public Color Color // 顏色屬性
#027 { get { return _color; }
#028 set { _color = value; }}
#029 public char Sex // 性別屬性
#030 { get { return _sex; }
#031 set { _sex = value; }}
#032 public float Weight // 體重屬性
#033 { get { return _weight; }
#034 set { _weight = value; }}
#035 }
有4條主要的規則以下。
爲持久化字段聲明訪問器(getters和setters)。
Cat爲它的全部可持久化字段聲明瞭getters和setters訪問器。用訪問器來替代直接訪問字段是個好習慣。也能夠經過字段(field)來使用NHibernate。屬性不必定須要聲明爲public的。NHibernate能夠對default、protected、internal或private的屬性執行持久化。
實現一個默認的構造方法(constructor):Cat有一個顯式的無參數默認構造方法。全部的持久化類都必須具備一個默認的構造方法(能夠不是public的),這樣NHibernate就可使用Constructor.Invoke()來實例化它們。
提供一個標識屬性(identifier property)(可選)。
建議使用不是sealed的類(可選)。
3.NHibernate映射
對象和關係數據庫之間的映射是用一個XML文檔(XML document)來定義的。這個映射文檔被設計爲易讀的,而且能夠手工修改。映射語言是以.NET爲中心的,意味着映射是按照持久化類的定義來建立的,而非表的定義。在Hibernate中XML映射文檔能夠手動定義,也有一些工具來輔助生成,包括Xdoclet、Middlegen和AndroMDA,可是在NHibernate文檔中並無上述的輔助工具,不過能夠採用MyGeneration這樣的代碼生成工具來生成XML配置文檔。下面是一個映射的例子:
#001 <?xml version="1.0" ?>
#002 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="Eg" assembly="Eg">
#003 <class name="Cat" table="CATS" discriminator-value="C">
#004 <id name="Id" column="uid" type="Int64">
#005 <generator class="hilo"/>
#006 </id>
#007 <discriminator column="subclass" type="Char"/>
#008 <property name="Name" type="Char"/>
#009 <property name="Color" not-null="false"/>
#010 <property name="Sex" not-null="false" update="false"/>
#011 <property name="Weight"/>
#012 <many-to-one name="Mate" column="mate_id"/>
#013 <set name="Kittens">
#014 <key column="mother_id"/>
#015 <one-to-many class="Cat"/>
#016 </set>
#017 <subclass name="DomesticCat" discriminator-value="D">
#018 <property name="Name" type="String"/>
#019 </subclass>
#020 </class>
#021 </hibernate-mapping>
全部的XML映射都須要使用nhibernate-mapping-2.0 schema。目前的schema能夠在NHibernate的資源路徑或者是NHibernate.dll的嵌入資源(Embedded Resource)中找到。NHibernate老是會優先使用嵌入在資源中的schema文件。在使用VisualStudio.NET時,用戶應該將hibernate-mapping拷貝到C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\ Packages\schemas\xml路徑中,以得到智能感知功能。
#002行:hibernate-mapping這個元素包括4個可選的屬性。schema屬性,指明瞭這個映射所引用的表所在的schema名稱。倘若指定了這個屬性,表名會加上所指定的schema的名字擴展爲全限定名。倘若沒有指定,表名就不會使用全限定名。default-cascade指定了未明確註明cascade屬性的屬性和集合類會採起什麼樣的默認級聯風格。auto-import屬性默認在查詢語言中可使用非全限定名的類名。default-access告訴用戶怎麼訪問屬性值。倘若有兩個持久化類,它們的非全限定名是同樣的,應該設置auto-import= "false"。倘若把一個「import」過的名字同時對應兩個類,NHibernate會拋出一個異常。
#003行:使用class元素來定義一個持久化類。name是持久化類(或者接口)的全限定名。table是對應的數據庫表名。discriminator-value(可選 - 默認和類名同樣)是一個用於區分不一樣的子類的值,在有多態行爲時使用。
#004行:使用id來標識主鍵字段,由於被映射的類必須聲明對應數據庫表主鍵字段。大多數類有一個屬性,爲每個實例包含惟一的標識。<id> 元素定義了該屬性到數據庫表主鍵字段的映射。
#005行:必須聲明的 <generator> 子元素是一個.NET類的名字,用來爲該持久化類的實例生成惟一的標識。其中hilo(高低位)使用一個高/低位算法來高效地生成Int6四、Int32 或者Int16類型的標識符。給定一個表和字段(默認分別是hibernate_unique_key 和next)做爲高位值的來源。高/低位算法生成的標識符只在特定的數據庫中是惟一的。
#007行:在「一棵對象繼承樹對應一個表」的策略中,<discriminator>元素是必需的,它聲明瞭表的識別器字段。識別器字段包含標誌值,用於告知持久化層應該爲某個特定的行建立哪個子類的實例。只能使用以下受到限制的類型:String,Char,Int32,Byte,Int16,Boolean,YesNo,TrueFalse。
#008-011行:<property>元素爲類聲明瞭一個持久化的屬性。name是屬性的名字,type(可選)是一個NHibernate類型的名字,not-null(可選)代表這個屬性是否爲空,update(可選-默認爲true)代表在用於UPDATE的SQL語句中是否包含這個字段。
#012行:經過many-to-one元素,能夠定義一種常見的與另外一個持久化類的關聯。這種關係模型是多對一關聯(其實是一個對象引用)。
#013-016行:<set>爲集合類標識,其中discriminator-value(可選 - 默認爲類名)用於區分每一個獨立的子類的值。
#017行:子類(subclass),多態持久化須要爲父類的每一個子類都進行聲明。對於上面建議的「每一棵類繼承樹對應一個表」的策略來講,就須要使用<subclass>聲明。
4.NHibernate應用實例
上面已經編寫好了Cat類和相應的映射文件,爲了正確調用Nhibernate,必須對web.config配置文件進行配置。具體配置代碼以下:
#001 <xml version="1.0" encoding="utf-8" ?>
#002 <configuration>
#003 <configSections>
#004 <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System Version=2.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
#005 </configSections>
#006 <nhibernate>
#007 <add
#008 key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
#009 <add
#010 key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver" />
#011 <add
#012 key="hibernate.connection.connection_string"
value="server=localhost;uid=sa;pwd=123;database=Sample" />
#013 <add
#014 key="hibernate.connection.isolation" value="ReadCommitted" />
#015 <add
#016 key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
#017 </nhibernate>
#018 </configuration>
#012行:hibernate.connection.connection_string的value爲鏈接服務器ConnectoinString。其餘的都是Nhibernate運行所必需的配置信息。
配置完web.config文件,在測試工程中引用NHibernate.dll和Eg,具體代碼以下。
#001 using System;
#002 using System.Collections.Generic;
#003 using System.Text;
#004 using NHibernate;
#005 using NHibernate.Cfg;
#006 using POJOLibrary;
#007 namespace Test
#008 {
#009 class Program
#010 {
#011 static void Main(string[] args)
#012 { Configuration c = new Configuration();
#013 c.AddAssembly("Eg");
#014 ISessionFactory factory = c.BuildSessionFactory();
#015 ISession s = factory.OpenSession();
#016 ITransaction t = s.BeginTransaction();
#017 Cat cat = new Cat();
#018 cat.Name = 「Bolo」;
#019 cat.Color = 「Black」;
#020 cat.Sex = 「Male」 ;
#021 cat.Weight = 「12」 ;
#022 s.Save(cat);
#023 t.Commit();}
#024 }
#025 }
NHibernate是經過Isession的實現類來提供功能的,上面代碼經過Itransaction打開一個事務t=s.BeginTransaction(),最後經過調用t.Commit()提交事務,將數據寫入數據庫中。
經過上述NHibernate的一個簡單的應用實例能夠看到,整個應用程序中沒有寫任何一句SQL語句。
雖然NHibernate目前不是很是的成熟,尚未達到實用化的水平,它常常在負荷有些大的時候崩潰,可是它脫胎於在Java社區有着巨大影響力的Hibernate,並且NHibernate在實際應用方面確實體現出了它的優點,基於上述緣由NHibernate必定會被愈來愈多的開發人員所接受,並且必定會被標準化。到目前爲止,NHibernate的最新版本爲1.1,官方站點[url]http://nhibernate.sourceforge.net/[/url]上目前的版本是beta 0.7.0.0。
1.5.3 Spring.Net介紹
Spring.Net是一個關注於.NET企業應用開發的應用程序框架,它可以提供很是豐富的功能,例如依賴注入(Dependency Injection),面向方面編程(Aspect Oriented Programming),數據訪問抽象以及ASP.NET集成等。Spring.NET脫胎於Java的Spring框架,其1.0版包括了一個功能完整的反轉控制容器和AOP函數庫,在後續的版本中將包含對ASP.NET、Remoting和數據訪問的支持。Spring.Net的框架如圖1-53所示。
圖1-53 Spring.Net的框架圖
1.控制反轉
IoC是近年來興起的一種思想,主要是協調各
組件
間相互的依賴關係,同時大大提升了組件的可移植性,組件的重用機會也變得更多。在傳統的實現中,由
程序
內部代碼來控制程序之間的關係。咱們常用new關鍵字來實現兩組鍵間關係的組合,這種實現地方式會形成組件之間耦合(一個好的設計,不但要實現代碼重用,還要將組件間關係解耦)。IoC很好地解決了該問題,它將實現組件間關係從程序內部提到外部容器,也就是說由容器在運行期將組件間的某種依賴關係動態注入組件中。
分離關注(Separation of Concerns:SOC)是產生IoC模式和
AOP
的最原始動力,經過功能分解可獲得關注點,這些關注能夠是組件、方面或服務。
從
GOF設計模式
中,咱們已經習慣一種思惟編程方式——接口驅動。接口驅動有不少好處,能夠提供靈活的子類實現,增長代碼穩定和健壯性等,可是接口必定是須要實現的,即以下語句必定要執行。
AInterface a = new AInterfaceImp();
AInterfaceImp是接口AInterface的子類,Ioc模式能夠根據須要延緩接口的實現,有個比喻:接口如同空的模型套,在必要時向模型套注射石膏,成爲一個模型實體。能夠人爲控制接口的實現完成「注射」。
IoC的實現方式有如下幾種:
基於接口的(Interface-based IoC,Type-1)。
基於設值的(Setter-based IoC,Type-2)。
基於構造的(Construtor-based IoC,Type-3)。
下面經過簡單的例子分別介紹上述幾種實現方式。
(1)Type-1。基於接口的設計方法一般是利用接口將調用者與實現者分離。
#001 public class Sport {
#002 private InterfaceBall ball; //InterfaceBall是定義的接口
#003 public void init() {
#004 //Basketball實現了InterfaceBall接口
#005 ball = (InterfaceBall) Class.forName("Basketball").newInstance();}
#006 }
Sport類在編譯期依賴於InterfaceBall的實現,爲了將調用者與實現者分離,能夠動態生成Basketball類並將其強制類型轉換爲InterfaceBall。
(2)Type-2。基於設值的設計方法是經過在類中暴露setter方法來實現依賴關係。
#001 public class Sport {
#002 private InterfaceBall _ball;
#003 public InterfaceBal1 ball
#004 {
#005 set{ _ball = value ;} }
#006 }
Spring.NET就是實現了該類型的輕量級容器。
(3)Type-3。經過構造方法完成依賴關係。
#001 public class Sport {
#002 private InterfaceBall ball;
#003 public Sport(InterfaceBall arg) {
#004 ball = arg; }
#005 }
因爲Type-3在構造期就造成了對象的依賴關係,因此對對象的重用變得困難。有些框架須要組件提供一個默認的構造方法,此時就顯現出Type-3的侷限性。一般全部的參數都是經過構造方法注入的,當對象間的依賴關係較多時,構造方法就顯得比較複雜,不利於單元測試。PicoContainer就是實現了Type-3依賴注入模式的輕量級容器。
2.Spring.NET庫
Spring.NET庫有6個基本組成部分,基本上涵蓋了Spring.NET框架的全部功能結構。
Spring.Core庫是Spring.NET框架最基礎的部分,它提供了依賴注入的功能。Spring.NET中大部分的函數庫都依賴於這個核心庫提供的功能,或者是對核心庫的擴展。IObjectFactory是核心容器接口,負責管理容器內的注入對象,而IApplicationContext則是IObjectFactory的繼承,它擴展了一些功能。
Spring.Aop庫爲商業邏輯對象提供了面向方面編程的支持,它爲建立企業應用和爲商業對象提供服務打下了基礎,是Spring核心庫中IoC容器的補充。
Spring.Web庫爲ASP.NET增長了不少功能,例如ASP.NET頁面的依賴注入,數據雙向綁定,爲ASP.NET提供母版頁功能,加強了本地化支持。全部的這些都是對ASP.NET很好的擴展。
Spring.Services庫能夠將任何一個「普通」對象(「普通」是指該對象不是繼承自特殊服務的基類)暴露成爲一個企業應用(COM+)或者遠程對象。由於對依賴注入和原數據屬性重載的支持,.NET 中的Web服務會得到更好的配置上的靈活性。一樣,該庫也提供了對Windows服務的支持。
Spring.Data庫爲.NET提供了一個數據訪問層的抽象,它可以用於從ADO.NET到多種ORM Provider的數據訪問提供者。它同時包含了一個ADO.NET抽象層,簡化了對ADO.NET的編碼和事務管理。
Spring.ORM庫提供了一個用於常見的對象—關係映射庫的綜合層,它提供了諸如對事務管理的支持等功能。
3.面向方面編程(AOP)
面向方面編程是對面向對象編程(OOP)的補充,是另一種思考編程框架的方法。面向對象是將應用分解成具備層次結構的對象;而面向方面編程則是把程序分解成方面或者關注點,使諸如事務管理等方面的模塊化成爲可能。Spring.NET中很關鍵的一個組件就是AOP框架。可以幫助Spring.NET的 IoC容器爲企業應用提供一個很是強大的中間件解決方案。
AOP用於Spring.NET能夠完成下列功能。
提供公開的企業服務,尤爲是做爲COM+公開服務的替代者。這些服務中最重要的服務是公開的事務管理,這是Spring.NET事務抽象的基礎。
容許用戶實現定製的方面,經過面向方面編程來補充面向對象編程的不足。
用戶不但能夠把Spring.NET AOP看做是可以不經過COM+就能夠提供公開事務管理的技術,並且還能夠充分發揮Spring.NET AOP框架的功能區實現定製方面。
經過上面的介紹讀者可能對AOP已經有了一個大體的瞭解,下面介紹幾個關於AOP的概念。
方面(Aspect):這個是一個讓讀者感受比較模糊的概念,它和一般意義上的方面不徹底同樣,它是對關注點的模塊化,這可能會橫切多個對象。事務管理是一個很是好的橫切關注點企業應用的例子。在Spring.NET中,方面做爲建議者或者監聽器的形式實現。
鏈接點(Jointpoint):程序運行期間的一些點,例如方法調用或者特殊的異常被拋出。
建議(Advice):AOP框架在一個特殊鏈接點上採起的動做。這些不一樣類型的建議包括「around」、「before」和「throws」 等建議。不少AOP框架,包括Spring.NET,都把一個建議模擬成一個監聽器,同時維護一個「around」鏈接點的監聽器鏈。
切點(Pointcut):一組鏈接點,用於指定建議應該激活的時間。一個AOP框架必須可以容許開發人員指定切點,例如,使用正則表達式。
介紹(Introduction):添加方法或域到建議類。Spring.NET容許介紹一個新的接口到任何一個建議對象中。例如,爲了簡化對對象狀態變化的跟蹤,可使用建議爲任何對象實現一個IAuditable接口。
目標對象:包含鏈接點的對象。
AOP代理:由AOP框架建立的對象,包括建議。在Spring.NET中,一個AOP代理是一個在運行期使用IL代碼生成的動態代理。
Weaving:裝配對象建立一個被建議對象。裝配工做發生在編譯期(例如使用Gripper-Loom .NET編譯器),也能發生在運行期。Spring.NET在運行期執行裝配動做。
4.Spring.NET應用實例
下面以經典的Movie Finder做爲Spring.NET應用實例來說解IoC容器的使用方法。實例的C#代碼能夠在Spring.NET發佈版的examples/Spring/Spring.Examples.MovieFinder目錄中找到。
(1)Movie Finder。MovieFinder例子的起始類是MovieApp類,這是具備單一應用程序入口點的普通.NET類。代碼以下所示:
#001 using System;
#002 namespace Spring.Examples.MovieFinder
#003 {
#004 public class MovieApp
#005 {
#006 public static void Main ()
#007 {
#008 }
#009 }
#010 }
如今想作的是得到一個對MovieFinder類實例的引用。這是Spring.NET例子,因此要從Spring.NET的IoC容器類IApplicationContext得到這個引用。應用程序配置文件中的IApplicationContext配置信息以下:
#001 <?xml version="1.0" encoding="utf-8" ?>
#002 <configuration>
#003 <configSections>
#004 <sectionGroup name="spring">
#005 <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
#006 <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
#007 </sectionGroup>
#008 </configSections>
#009 <spring>
#010 <context>
#011 <resource uri="config://spring/objects"/>
#012 </context>
#013 <objects>
#014 <description>An example that demonstrates simple IoC features.</description>
#015 </objects>
#016 </spring>
#017 </configuration>
將在應用程序示例中用到的對象配置成嵌套在<objects/>元素中的<object/>元素。
(2)得到IApplicationContext應用。代碼以下所示:
#001 using System;
#002 using System.Configuration;
#003 using Spring.Context;
#004 ...
#005 public static void Main ()
#006 { IApplicationContext ctx = ContextRegistry.GetContext();}
#007 ...
如上所述,using System.Configuratoin和using Spring.Context兩條using語句被加到了MovieApp類文件中。其中,System.Configuration命名空間可讓應用程序存取保存在配置文件中的Spring.NET的IoC容器的定義;Spring.Context命名空間可讓應用程序存取IApplicationContext類,這個類是應用程序存取Spring.NET所提供的功能的主要方法。
方法main得到一個IApplicationContext的實現,它的配置信息已經被寫在應用程序配置文件內名爲<objects/>的節中。
(3)第一個對象的定義。到目前爲止,在應用程序配置文件中尚未對象定義,因此下面定義一個對象。MovieLister實例的XML定義以下所示。
#001 ...
#002 <objects>
#003 <object name="MyMovieLister"
#004 type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
#005 </object>
#006 </object>
#007 ...
#003行:MyMovieLister是該對象的惟一標識符,使用這個標識符,這個對象的實例就可以被以下所示的代碼中的IApplicationContext引用所獲取。
#001 ...
#002 public static void Main ()
#003 { IApplicationContext ctx = ContextRegistry.GetContext();
#004 MovieLister lister = (MovieLister) ctx.GetObject ("MyMovieLister");}
#005 ...
lister實例仍然沒有與IMovieFinder接口相應的實現注入。此時若是使用MoviesDirectedBy方法會致使NullReferenceException異常發生,由於lister實例仍然尚未對IMovieFinder的引用。注入到lister實例中的IMovieFinder接口實現的XML配置定義以下。
#001 ...
#002 <objects>
#003 ...
#004 <object name="MyMovieFinder"
#005 type="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
#006 </object>
#007 ...
#008 </object>
#009 ...
(4)設值注入。下面要作的是把以MyMovieFinder爲標識符的IMovieFinder實例注入到以MyMovieLister爲標識符的MovieLister實例中。這個注入動做使用設值注入的方法,代碼以下所示:
#001 ...
#002 <objects>
#003 <object name="MyMovieLister"
#004 type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
#005 <!-- using setter injection... -->
#006 <property name="movieFinder" ref="MyMovieFinder"/>
#007 </object>
#008 <object name="MyMovieFinder"
#009 type="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
#010 </object>
#011 </objects>
#012 ...
當IApplicationContext接口取得了MyMovieLister對象之後,Spring.NET的IoC容器將會把對MyMovieLister對象的引用注入到MyMovieLister對象的MovieFinder屬性中去。這樣,在程序中引用的MovieFinder對象即配置完畢,能夠列出某導演導過的全部電影。
#001 ...
#002 public static void Main ()
#003 {
#004 IApplicationContext ctx = ContextRegistry.GetContext();
#005 MovieLister lister = (MovieLister) ctx.GetObject ("MyMovieLister");
#006 Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni");
#007 Console.WriteLine ("\nSearching for movie...\n");
#008 foreach (Movie movie in movies)
#009 {Console.WriteLine (
#010 string.Format ("Movie Title = '{0}', Director = '{1}'.",
#011 movie.Title, movie.Director));}
#012 Console.WriteLine ("\nMovieApp Done.\n\n");
#013 }
#014 ...
也可使用構造注入的方法,讀者能夠本身考慮構造注入方法的實現方式,這裏就再也不具體介紹。
如今Spring.Net的1.0.2版本已經發布,讀者能夠經過訪問[url]http://sourceforge.net/[/url] projects/ springnet下載。