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();} |
AOP原理解析及Castle、Autofac、Unity框架使用的更多相关文章
- [Solution] DI原理解析及Castle、Unity框架使用
本节目录 DI介绍 DI基本原理 DI框架 Castle Windsor Unity Autofac Spring.Net DI介绍 控制反转(Inversion of Control,英文缩写为Io ...
- [Solution] AOP原理解析及Castle、Autofac、Unity框架使用
本节目录: AOP介绍 AOP基本原理 AOP框架 Castle Core Castle Windsor Autofac Unity AOP介绍 面向切面编程(Aspect Oriented Prog ...
- Spring笔记(3) - debug源码AOP原理解析
案例 @EnableAspectJAutoProxy//开启基于注解的aop模式 @Configuration public class AOPConfig { //业务逻辑类加入容器中 @Bean ...
- Spring AOP原理解析
原文链接请参见:http://blog.csdn.net/u010723709/article/details/47839307
- [置顶]
滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理
上周末,滴滴与360都开源了各自的插件化框架,VirtualAPK与RePlugin,作为一个插件化方面的狂热研究者,在周末就迫不及待的下载了Virtualapk框架来进行研究,本篇博客带来的是Vir ...
- ABP中动态WebAPI原理解析
ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类 ...
- SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP
AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...
- Spring IOC设计原理解析:本文乃学习整理参考而来
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- Spring源码分析之AOP从解析到调用
正文: 在上一篇,我们对IOC核心部分流程已经分析完毕,相信小伙伴们有所收获,从这一篇开始,我们将会踏上新的旅程,即Spring的另一核心:AOP! 首先,为了让大家能更有效的理解AOP,先带大家过一 ...
随机推荐
- Win7 资源管理器右键固定的文件夹不见了
把常用的文件夹固定到任务栏的资源管理器右键菜单中 某天突然就不见了! %APPDATA%\Microsoft\Windows\Recent\AutomaticDestinations “最近" ...
- VS编译静态库 .lib 其中Release 版本比Debug版本要大好多原因
如果工程代码使用了: 把此选项关闭即可减少库大小不少:
- LUA 环境
LUA中环境是指一个函数执行的表,即一个函数在什么表中执行. 这里的函数是特殊的,是loadfile("x.lua")的返回值. loadfile("x.lua" ...
- Android开发实战之补间动画和属性动画
说起动画,其实一点也不陌生,在使用一款app的时候为了优化用户体验,多多少少的,都会加入动画. 安卓中的动画,分为两大类:补间动画和属性动画.本篇博文会详细介绍总结这两大动画,希望本篇博文对你的学习和 ...
- jsp实现查询与展示功能
今天做了一天的这个功能,开始是数据库一直打不开,显示Class not found,一直调试,调试了一下午.原来是mysql的jar包,必须要放到WEB-INF这个目录下的lib文件夹中,然后bui ...
- CSS的编写规范
一.前言 如上图,页面在渲染和画图时,耗时还是比较多的,这就对我们的编写要求愈加严格. 我们有很多方法来减少上图所示的页面加载耗时的,比如 但是更多的还是在于平时的编写规范,我们需要了解浏览器,让他更 ...
- MySQL多表查询回顾
----------------------siwuxie095 MySQL 多表查询回顾 以客户和联系人为例(一对多) 1.内连接 /*内连接写法一*/ select * from t_custom ...
- Oracle——约束
NOT NULLUNIQUE PRIMARY KEYFOREIGN KEYCHECK 如果不指定约束名 ,Oracle server 自动按照 SYS_Cn 的格式指定约束名 --指定约束名 CREA ...
- 3.3.6-1 ArrayBlockingQueue简单分析
构造方法:public ArrayBlockingQueue(int capacity) { this(capacity, false); } public ArrayBlockingQueue(in ...
- Hadoop分布式模式下SSH免密码登录
1.Hadoop中为什么要配置免密码登录 最近在学习Hadoop,在集群中,Hadoop控制脚本依赖SSH来执行针对整个集群的操作.例如,某个脚本能够终止并重启集群中的所有守护进程.所以,需要安装SS ...