Spring.NET学习笔记12——面向切面编程(基础篇) Level 300
AOP即面向切面編程(Aspect Oriented Programming的縮寫),是OOP(面向?qū)ο缶幊?的一種延續(xù)形式。是通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)在不修改源代碼的情況下給程序動(dòng)態(tài)統(tǒng)一添加功能的一種技術(shù),它從一個(gè)不同于OOP的角度來看待程序的結(jié)構(gòu):OOP將應(yīng)用程序分解為一系列表現(xiàn)為繼承關(guān)系的對(duì)象;AOP 則把程序分解為一系列方面(aspects)或者關(guān)注點(diǎn)(concerns)。AOP將諸如事務(wù)管理等本來橫向分布在多個(gè)對(duì)象中的關(guān)注點(diǎn)進(jìn)行了模塊化處理(這些關(guān)注點(diǎn)也常稱為橫切(crosscutting)關(guān)注點(diǎn))。在Spring.NET中提供了面向切面編程的豐富支持,允許通過分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級(jí)服務(wù)(例如審計(jì)(auditing)和事務(wù)(transaction)管理)進(jìn)行內(nèi)聚性的開發(fā)。應(yīng)用對(duì)象只實(shí)現(xiàn)它們應(yīng)該做的——完成業(yè)務(wù)邏輯——僅此而已。它們并不負(fù)責(zé)(甚至是意識(shí))其它的系統(tǒng)級(jí)關(guān)注點(diǎn),例如日志或事務(wù)支持。
下面我舉個(gè)例子來說明這一切:
場景:業(yè)務(wù)類CompanyManager在調(diào)用Save方法的時(shí)候需要調(diào)用SecurityManager類判斷權(quán)限是否足夠(圖1)。
圖1
?
準(zhǔn)備條件:
????public?class?CompanyDao????{
????????public?void?Save()
????????{
????????????Console.WriteLine("保存數(shù)據(jù)");
????????}
????}
?
????public?interface?ICompanyManager????{
????????string?UserName?{?get;?set;?}
????????void?Save();
????}
?
????public?interface?ISecurityManager????{
????????bool?IsPass(string?userName);
????}
?
SecurityManager????public?class?SecurityManager?:?ISecurityManager
????{
????????/**////?<summary>
????????///?判斷權(quán)限
????????///?</summary>
????????///?<param?name="userName"></param>
????????///?<returns></returns>
????????public?bool?IsPass(string?userName)
????????{
????????????return?userName?==?"admin";
????????}
????}
?
第一種實(shí)現(xiàn)方式,我們通常會(huì)這樣做:直接在CompanyManager類中調(diào)用ISecurityManager接口的IsPass方法判斷權(quán)限。
?
SimpleCompanyManagerpublic?class?SimpleCompanyManager?:?ICompanyManager
????{
????????可通過外部注入的屬性#region?可通過外部注入的屬性
????????public?string?UserName?{?get;?set;?}
????????public?CompanyDao?Dao?{?get;?set;?}
????????#endregion
????????public?void?Save()
????????{
????????????//判斷權(quán)限
????????????ISecurityManager?security?=?new?SecurityManager();
????????????if?(security.IsPass(UserName))
????????????{
????????????????//執(zhí)行業(yè)務(wù)方法
????????????????//.
????????????????//調(diào)用DAO層方法
????????????????Dao.Save();
????????????}
????????????else
????????????{
????????????????//執(zhí)行其它業(yè)務(wù)方法
????????????????Console.WriteLine("您沒有該權(quán)限");
????????????}
????????}
????}
?
這樣CompanyManager類與ISecurityManager或SecurityManager會(huì)發(fā)生業(yè)務(wù)性耦合。聰明的朋友會(huì)發(fā)現(xiàn)在GOF(設(shè)計(jì)模式)中有一種模式(代理模式)可以解除這種耦合。
第二種實(shí)現(xiàn)方式,代理模式(Proxy Pattern):什么是代理模式?是給某一個(gè)對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象控制對(duì)源對(duì)象的引用。代理就是一個(gè)人或一個(gè)機(jī)構(gòu)代表另一個(gè)人或者一個(gè)機(jī)構(gòu)采取行動(dòng)。某些情況下,客戶不想或者不能夠直接引用一個(gè)對(duì)象,代理對(duì)象可以在客戶和目標(biāo)對(duì)象直接起到中介的作用。客戶端分辨不出代理主題對(duì)象與真實(shí)主題對(duì)象。代理模式可以并不知道真正的被代理對(duì)象,而僅僅持有一個(gè)被代理對(duì)象的接口,這時(shí)候代理對(duì)象不能夠創(chuàng)建被代理對(duì)象,被代理對(duì)象必須有系統(tǒng)的其他角色代為創(chuàng)建并傳入(圖2)。
圖2
????public?class?CompanyManager?:?ICompanyManager
????{
????????可通過外部注入的屬性#region?可通過外部注入的屬性
????????public?string?UserName?{?get;?set;?}
????????public?CompanyDao?Dao?{?get;?set;?}
????????#endregion
????????public?void?Save()
????????{
????????????//執(zhí)行業(yè)務(wù)方法
????????????//.
????????????//調(diào)用DAO層方法
????????????Dao.Save();
????????}
????}
?
CompanyProxyManager????public?class?CompanyProxyManager?:?ICompanyManager
????{
????????public?string?UserName?{?get;?set;?}
????????private?ICompanyManager?target?=?new?CompanyManager();
????????public?void?Save()
????????{
????????????//判斷權(quán)限
????????????ISecurityManager?security?=?new?SecurityManager();
????????????if?(security.IsPass(UserName))
????????????{
????????????????//調(diào)用目標(biāo)對(duì)象Save方法
????????????????target.Save();
????????????}
????????????else
????????????{
????????????????Console.WriteLine("您沒有該權(quán)限");
????????????}
????????}
????}
?
這樣,CompanyManager類就不必與判斷權(quán)限的類SecurityManager耦合,但是這種方式實(shí)現(xiàn)起來比較麻煩。
?
第三種實(shí)現(xiàn)方式,Spring.NET提供的AOP:AopAlliance.Intercept.IMethodInterceptor接口和ProxyFactory類的組合。
????public?class?AroundAdvice?:?IMethodInterceptor
????{
????????//權(quán)限系統(tǒng)類(可外部注入)
????????private?ISecurityManager?manager?=?new?Service.SecurityManager();
????????public?object?Invoke(IMethodInvocation?invocation)
????????{
????????????//攔截Save方法
????????????if?(invocation.Method.Name?==?"Save")
????????????{
????????????????ICompanyManager?target?=?(ICompanyManager)invocation.Target;
????????????????return?manager.IsPass(target.UserName)???invocation.Proceed()?:?null;
????????????}
????????????else
????????????{
????????????????return?invocation.Proceed();
????????????}
????????}
????}
?
Program????class?Program
????{
????????static?void?Main(string[]?args)
????????{
????????????ICompanyManager?target?=?new?CompanyManager()?{?Dao?=?new?CompanyDao(),?UserName?=?"admin"?};
????????????
????????????ProxyFactory?factory?=?new?ProxyFactory(target);
????????????factory.AddAdvice(new?AroundAdvice());
????????????ICompanyManager?manager?=?(ICompanyManager)factory.GetProxy();
????????????manager.Save();
????????????Console.ReadLine();
????????}
????}
?
輸出:保存數(shù)據(jù)
?
Spring.NET利用System.Reflection.Emit命名空間下的類在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建IL代碼來生成AOP代理。這使得代理(的創(chuàng)建)非常高效,并且不受任何繼承層次的限制。
?
參考:Spring.NET中文手冊
李會(huì)軍博客代理模式http://www.cnblogs.com/terrylee/archive/2006/05/18/403382.html
?
代碼下載
?
?
返回目錄
總結(jié)
以上是生活随笔為你收集整理的Spring.NET学习笔记12——面向切面编程(基础篇) Level 300的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到女儿生病是什么意思周公解梦
- 下一篇: 做梦梦到被绿了是什么意思