AOP原理解析及Castle、Autofac、Unity框架使用

轉自:https://www.cnblogs.com/neverc/p/5241466.html

AOP介紹

面向切面編程(Aspect Oriented Programming,英文縮寫為AOP),通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。

AOP是OOP的延續,是軟件開發中的一個熱點.

常用于:

Authentication?

Caching

Lazy loading

Transactions

?

AOP基本原理

普通類

1
2
3
4
5
6
7
8
9
class?Person : MarshalByRefObject
{
????public?string?Say()
????{
????????const?string?str =?"Person's say is called";
????????Console.WriteLine(str);
????????return?str;
????}
}

代理類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public?class?Proxy<T> : RealProxy?where?T :?new()
{
????private?object?_obj;
????public?Proxy(object?obj)
????????:?base(typeof(T))
????{
????????_obj = obj;
????}
????public?override?IMessage Invoke(IMessage msg)
????{
????????Console.WriteLine("{0}:Invoke前", DateTime.Now);
????????var?ret = ((IMethodCallMessage)msg).MethodBase.Invoke(_obj,?null);
????????Console.WriteLine("{0}:Invoke后", DateTime.Now);
????????return?new?ReturnMessage(ret,?null, 0,?null,?null);
????}
}

執行

1
2
3
4
5
6
7
8
9
10
static?void?Main(string[] args)
{
????var?per =?new?Proxy<Person>(new?Person()).GetTransparentProxy()?as?Person;
????if?(per !=?null)
????{
????????var?str = per.Say();
????????Console.WriteLine("返回值:"?+ str);
????}
????Console.ReadKey();
}

?

AOP框架

AOP有動態代理和靜態IL織入.

本節主要介紹動態代理方式,靜態可參考PostSharp.

?

Castle Core

原理:本質是創建繼承原來類的代理類.重寫虛方法實現AOP功能.

?

只需引用:

Install-Package Castle.Core

(在Castle的2.5以上版本,已經將 Castle.DynamicProxy2.dll 里有內容,集成到 Castle.Core.dll 中。)

?

Simple Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public?abstract?class?Person
{
????public?virtual?void?SayHello()
????{
????????Console.WriteLine("我是{0}方法",?"SayHello");
????}
????public?virtual?void?SayName(string?name)
????{
????????Console.WriteLine("我是{0}方法,參數值:{1}",?"SayName", name);
????}
????public?abstract?void?AbstactSayOther();
????public?void?SayOther()
????{
????????Console.WriteLine("我是{0}方法",?"SayOther");
????}
}

?

interceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public?class?SimpleInterceptor : StandardInterceptor
{
????protected?override?void?PreProceed(IInvocation invocation)
????{
????????Console.WriteLine("攔截器調用方法前,方法名是:{0}。", invocation.Method.Name);
????}
????protected?override?void?PerformProceed(IInvocation invocation)
????{
????????Console.WriteLine("攔截器開始調用方法,方法名是:{0}。", invocation.Method.Name);
????????var?attrs = invocation.MethodInvocationTarget.Attributes.HasFlag(MethodAttributes.Abstract);//過濾abstract方法
????????if?(!attrs)
????????{
????????????base.PerformProceed(invocation);//此處會調用真正的方法 invocation.Proceed();
????????}
????}
????protected?override?void?PostProceed(IInvocation invocation)
????{
????????Console.WriteLine("攔截器調用方法后,方法名是:{0}。", invocation.Method.Name);
????}
}

?

Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static?void?Main(string[] args)
{
????var?generator =?new?ProxyGenerator();???????//實例化【代理類生成器】?
????var?interceptor =?new?SimpleInterceptor();??//實例化【攔截器】?
????//使用【代理類生成器】創建Person對象,而不是使用new關鍵字來實例化?
????var?person = generator.CreateClassProxy<Person>(interceptor);
????Console.WriteLine("當前類型:{0},父類型:{1}", person.GetType(), person.GetType().BaseType);
????Console.WriteLine();
????person.SayHello();//攔截
????Console.WriteLine();
????person.SayName("Never、C");//攔截
????Console.WriteLine();
????person.SayOther();//普通方法,無法攔截????
????person.AbstactSayOther();//抽象方法,可以攔截????
????Console.ReadLine();
}

?

Castle Windsor

特性式AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
public?interface?IPerson
{
????void?Say();
}
[Interceptor(typeof(LogInterceptor))]
public?class?Person : IPerson
{
????public?void?Say()
????{
????????Console.WriteLine("Person's Say Method is called!");
????}
}

?

1
2
3
4
5
6
7
8
9
public?class?LogInterceptor : IInterceptor
{
????public?void?Intercept(IInvocation invocation)
????{
????????Console.WriteLine("{0}:攔截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
????????invocation.Proceed();
????????Console.WriteLine("{0}:攔截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
????}
}

?

1
2
3
4
5
6
7
8
9
10
11
static?void?Main(string[] args)
{
????using?(var?container =?new?WindsorContainer())
????{
????????container.Register(Component.For<Person, IPerson>());
????????container.Register(Component.For<LogInterceptor, IInterceptor>());
????????var?person = container.Resolve<IPerson>();
????????person.Say();
????}
????Console.ReadKey();
}


非侵入式AOP

1
2
3
4
5
6
7
8
9
10
11
12
public?interface?IPerson
{
????void?Say();
}
public?class?Person : IPerson
{
????public?void?Say()
????{
????????Console.WriteLine("Person's Say Method is called!");
????}
}

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
internal?static?class?LogInterceptorRegistrar
{
????public?static?void?Initialize(WindsorContainer container)
????{
????????container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
????}
????private?static?void?Kernel_ComponentRegistered(string?key, IHandler handler)
????{
????????handler.ComponentModel.Interceptors.Add(new?InterceptorReference(typeof(LogInterceptor)));
????}
}
public?class?LogInterceptor : IInterceptor
{
????public?void?Intercept(IInvocation invocation)
????{
????????Console.WriteLine("{0}:攔截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
????????invocation.Proceed();
????????Console.WriteLine("{0}:攔截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
????}
}

?

1
2
3
4
5
6
7
8
9
10
11
12
static?void?Main(string[] args)
{
????using?(var?container =?new?WindsorContainer())
????{
????????container.Register(Component.For<IInterceptor, LogInterceptor>());//先注入攔截器
????????LogInterceptorRegistrar.Initialize(container);
????????container.Register(Component.For<IPerson, Person>());
????????var?person = container.Resolve<IPerson>();
????????person.Say();
????}
????Console.ReadKey();
}

?

Autofac

Install-Package Autofac.Aop

通過特性標簽綁定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class?LogInterceptor : IInterceptor
?{
?????public?void?Intercept(IInvocation invocation)
?????{
?????????Console.WriteLine("{0}:攔截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
?????????invocation.Proceed();
?????????Console.WriteLine("{0}:攔截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
?????}
?}
?public?interface?IPerson
?{
?????void?Say();
?}
?[Intercept(typeof(LogInterceptor))]
?public?class?Person : IPerson
?{
?????public?void?Say()
?????{
?????????Console.WriteLine("Person's Say Method is called!");
?????}
?}

?

啟用攔截器執行

1
2
3
4
5
6
7
8
9
10
11
static?void?Main(string[] args)
{
????var?builder =?new?ContainerBuilder();
????builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors();
????builder.RegisterType<LogInterceptor>();
????using?(var?container = builder.Build())
????{
????????container.Resolve<IPerson>().Say();
????}
????Console.ReadLine();
}

?

或采用非侵入性方法(去掉class上的特性仍可以)

1
2
3
4
5
6
7
8
9
10
11
static?void?Main(string[] args)
{
????var?builder =?new?ContainerBuilder();
????builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors().InterceptedBy(typeof(LogInterceptor));
????builder.RegisterType<LogInterceptor>();
????using?(var?container = builder.Build())
????{
????????container.Resolve<IPerson>().Say();
????}
????Console.ReadLine();
}

  

?

Unity

Unity默認提供了三種攔截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。

TransparentProxyInterceptor:代理實現基于.NET Remoting技術,它可攔截對象的所有函數。缺點是被攔截類型必須派生于MarshalByRefObject。

InterfaceInterceptor:只能對一個接口做攔截,好處時只要目標類型實現了指定接口就可以攔截。

VirtualMethodInterceptor:對virtual函數進行攔截。缺點是如果被攔截類型沒有virtual函數則無法攔截,這個時候如果類型實現了某個特定接口可以改用

?

Install-Package Unity.Interception

1
2
3
4
5
6
7
8
9
10
11
12
13
public?class?MyHandler : ICallHandler
{
????public?int?Order {?get;?set; }//這是ICallHandler的成員,表示執行順序
????public?IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
????{
????????Console.WriteLine("方法執行前");
????????//這之前插入方法執行前的處理
????????var?retvalue = getNext()(input, getNext);//在這里執行方法
????????//這之后插入方法執行后的處理
????????Console.WriteLine("方法執行后");
????????return?retvalue;
????}
}

?

1
2
3
4
5
6
7
public?class?MyHandlerAttribute : HandlerAttribute
{
????public?override?ICallHandler CreateHandler(IUnityContainer container)
????{
????????return?new?MyHandler();//返回MyHandler
????}
}

?

1
2
3
4
5
6
7
8
9
10
11
12
13
public?interface?IPerson
{
????void?Say();
}
[MyHandler]
public?class?Person : IPerson
{
????public?virtual?void?Say()
????{
????????Console.WriteLine("Person's Say Method is called!");
????}
}

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static?void?Main(string[] args)
{
????using?(var?container =?new?UnityContainer())
????{
????????container.AddNewExtension<Interception>();
????????//1.TransparentProxyInterceptor
????????//container.Configure<Interception>().SetInterceptorFor<IPerson>(new TransparentProxyInterceptor());
????????//2.InterfaceInterceptor (使用1,2,3均可,這種侵入性最小)
????????container.Configure<Interception>().SetInterceptorFor<IPerson>(new?InterfaceInterceptor());
????????//3.VirtualMethodInterceptor
????????//container.Configure<Interception>().SetInterceptorFor<Person>(new VirtualMethodInterceptor());
????????container.RegisterType<IPerson, Person>();
????????container.Resolve<IPerson>().Say();
????}
????Console.ReadKey();
}

轉載于:https://www.cnblogs.com/chenyishi/p/9676011.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451255.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bootstrap validator 提供了哪些驗證函數

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 目前提供的校驗方法有&#xff1a; "notEmpty" : "不能為空", "password" : "請輸入正確的密碼&q…

帕累托分布(Pareto distributions)、馬太效應

什么是帕累托分布 帕累托分布是以意大利經濟學家維弗雷多帕雷托命名的。 是從大量真實世界的現象中發現的冪次定律分布。這個分布在經濟學以外&#xff0c;也被稱為布拉德福分布。 帕累托因對意大利20%的人口擁有80%的財產的觀察而著名&#xff0c;后來被約瑟夫朱蘭和其他人概括…

兩個class寫在同一個java文件中

第一種&#xff1a; 一個public類&#xff0c;多個非public類&#xff0c;例如&#xff1a;public class A&#xff5b;&#xff5d;class B&#xff5b;&#xff5d;第二個class前面不能加public。 第二種&#xff1a; 第二種是內部類&#xff0c;寫在公共類體里面的&#xff…

微信小程序的一些數據調用方式

1.模板數據的調用 一張圖了解一下在wxml頁調用預先定義好的模板&#xff1a; 可以看到上面調用了兩個模板&#xff0c;數據調用卻是不同的&#xff0c;obj是一個對象&#xff0c;對象內包含多個鍵值對形式的數據&#xff1b; tabbar是一個一維數組&#xff0c;每個數組項又都是…

手機廠商探路互聯網:硬件高利潤時代已成歷史

華為消費者業務集團CEO兼終端公司董事長余承東近日出席“2012年全球移動互聯網大會”期間證實&#xff0c;華為計劃與奇虎360合作推出一款智能手機。 余承東表示&#xff0c;華為終端將嘗試與多家互聯網公司就智能手機業務展開合作&#xff0c;但他未透露與奇虎360合作的更多細…

解決:按截圖 ctrl+alt+a QQ聊天窗口就自動最小化(QQ以外的可以截圖)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、問題如題 &#xff0c;想截圖QQ聊天記錄都不行 二、 解決方法&#xff1a; 如圖找到QQ截圖按鈕&#xff0c;點擊下拉倒三角&…

數據庫備份DBS商業化發布

數據庫備份DBS商業化發布將在2018年7月11日 15:00-16:00直播&#xff0c;敬請關注&#xff01; 數據庫備份DBS為數據庫提供連續數據保護、低成本的備份服務。 它可以為多種環境的數據提供強有力的保護&#xff0c;包括企業數據中心、其他云廠商及公共云。數據庫備份提供數據備份…

堡壘機(跳板機)

堡壘機&#xff08;跳板機&#xff09;&#xff1f;現在一定規模互聯網企業&#xff0c;往往都擁有大量服務器&#xff0c;如何安全并高效的管理這些服務器是每個系統運維或安全運維人員必要工作。現在比較常見的方案是搭建堡壘機環境作為線上服務器的入口&#xff0c;所有服務…

2018-09-18

12.1 LNMP架構介紹 和LAMP不同的是&#xff0c;提供web服務的是Nginx并且php是作為一個獨立服務存在的&#xff0c;這個服務叫做php-fpmNginx直接處理靜態請求&#xff0c;動態請求會轉發給php-fpm12.2 MySQL安裝 二進制免編譯包安裝 [rootlocalhost ~]# cd /usr/local/src/ [r…

舉例說明Java中代碼塊的執行順序

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 結論 這里先把整理好的結論拋給大家&#xff0c;然后我在寫個程序來驗證我們的結論。在Java類被new的過程中&#xff0c;執行順序如…

Google 正式開源 Jib ,幫助 Java 應用快速容器化

Google 本周宣布開源一款新的 Java 工具 Jib &#xff0c;旨在讓開發者使用他們熟悉的工具更輕松地將 Java 應用程序容器化。在7月9日發布的博客文章中&#xff0c;Google 軟件工程師 Appu Goundan 和 Qingyang Chen 將 Jib 描述為一個容器鏡像構建器&#xff0c;旨在處理將 Ja…

“公敵”京東:眾同行將其拖入價格戰

倒京東語錄 當當網董事長李國慶&#xff1a; 京東的資金只能維持到8月至12月。當當網是賺一個花兩個&#xff0c;而京東則是賺一個花四個。 蘇寧電器董事長張近東&#xff1a; 我至今沒有看見過哪個企業能通過這種方式取得最后勝利。這種違背正常商業邏輯的做法&#xff0c…

跨域與跨域訪問

什么是跨域 跨域是指從一個域名的網頁去請求另一個域名的資源。比如從www.baidu.com 頁面去請求 www.google.com 的資源。跨域的嚴格一點的定義是&#xff1a;只要 協議&#xff0c;域名&#xff0c;端口有任何一個的不同&#xff0c;就被當作是跨域 為什么瀏覽器要限制跨域訪…

thymeleaf 使用javascript定義數組報錯

js中免不了的要用的數組&#xff0c;一維的二維的三維的 但是當用到thymeleaf作為模版時候會有一些坑&#xff0c;導致數組不能用 org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "{checkbox: true, fixed: true}, {field: origi…

解決:Failed to execute goal on project aopcore: Could not resolve dependencies for project com.cmos:

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、問題描述 maven工程 jar包無法下載&#xff0c;報錯如下 &#xff1a; [ERROR] Failed to execute goal on project aopcore: Cou…

從Xbox和Zune中學到的四門創業課

導讀&#xff1a;微軟前娛樂與設備部門總裁Robbie Bach領導他的團隊&#xff0c;實現了Xbox的暢銷。然而&#xff0c;他領導該部門推出的Zune音樂播放器&#xff0c;卻沒那么成功。從Robbie這兩個經歷中&#xff0c;我們們能學到什么&#xff1f;本文是Robbie自己的總結&#x…

服務容錯保護斷路器Hystrix之七:做到自動降級

從《高可用服務設計之二&#xff1a;Rate limiting 限流與降級》中的“自動降級”中&#xff0c;我們這邊將系統遇到“危險”時采取的整套應急方案和措施統一稱為降級或服務降級。想要幫助服務做到自動降級&#xff0c;需要先做到如下幾個步驟&#xff1a; 可配置的降級策略&am…

from表單提交和JSON區別

form表單是“鍵值對”的數據格式&#xff0c;例如&#xff1a; a1&b2&c3 而json格式則與之不同&#xff0c;如下&#xff1a; {"a":1,"b":2,"c":3} 傳遞的數據比較簡單&#xff0c;那么兩種方式基本上沒什么大區別&#xff08;當然后臺接…

在一個數組中,如何確定所需元素在數組中的位置.

package wac.wev.LianXi; public class CiShu {public static void main(String[] args){//創建一個數組int[] arr {101,23,123,34,13};int y Yuan(arr,13);System.out.println(y);}//1)明確返回值:int//2)明確形式參數:int[] arr 和 int value(value表示所需元素)public stati…

Java實現Excel導入數據庫,數據庫中的數據導入到Excel

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 實現的功能&#xff1a; Java實現Excel導入數據庫&#xff0c;如果存在就更新數據庫中的數據導入到Excel1、添加jxl.jar mysql-connect…