AOP in .NET
来源:互联网 发布:淘宝空间协议在哪里 编辑:程序博客网 时间:2024/04/30 11:01
本文将假设读者对AOP的相关原理概念有了一定的了解,直接从第三部分开始。
实现方式
From Ayende Rahien’s blog post
Approach
Advantages
Disadvantages
Remoting Proxies
Easy to implement, because of the .Net framework support
Somewhat heavy weight
Can only be used on interfaces or MarshalByRefObjects
Deriving from ContextBoundObject
Easiest to implement
Native support for call interception
Very costly in terms of performance
Compile-time subclassing
( Rhino Proxy )
Easiest to understand
Interfaces or virtual methods only
Runtime subclassing
( Castle Dynamic Proxy )
Easiest to understand
Very flexible
Complex implementation (but already exists)
Interfaces or virtual methods only
Hooking into the profiler API
( Type Mock )
Extremely powerful
Performance?
Complex implementation (COM API, require separate runner, etc)
Compile time IL-weaving
( Post Sharp / Cecil )
Very powerful
Good performance
Very hard to implement
Runtime IL-weaving
( Post Sharp / Cecil )
Very powerful
Good performance
Very hard to implement
来看看具体的缺点
- 使用remoting proxies / ContextBoundObject
- 无法对this的调用进行intercept,因为CLR保证this不会是代理
- 性能影响很大,比如使用继承ContextBoundObject的方式会造成运行时context切换
- SubClassing
- 需要类型不能为sealed且只能override virtual方法。
- 不能改写constructor
- Weaving
- 如果是source code层级的织入,需要对每种.Net支持的语言提供分别的支持
- 无论是source code层级还是IL层级的织入,都有可能在类型变更的时候遭到破坏/给类型造成破坏。
现有的一些.Net的AOP框架
Project
Status
License
Approach
Document & Support
More Description
AspectDng
Updated to 1.0.3
GPL 2+
Look here for detail
Perhaps Compile time IL injection?
This project is not supported any more.
Relies on Cecil.
Post Sharp
Updated to 2.0.8.1323
Free, Commercial
Compile time IL injection
Commercial support.
Well documented.
Castle dynamic proxy
Updated to 2.5.2 at November 15, 2010
Dynamic proxy
Out of datedocuments
Multipurpose framework
EOS
Updated to 0.3.4
Free, Commercial
Custom Complier
Only tested with .Net 1.x
Aspect.NET
Updated to Beta(Version 8) at July 29 2009
Perhaps Compile time IL injection?
Relies on Phoenix
Aspect Sharp (Aspect#)
Updated to 2.1.1.0 on May 16, 2005
Apache 2.0
?
Compose*
Updated to 0.9.5 at August 5 2008
BSD, LGPL
?
Rapier-LOOM.NET
Updated to 2.21 at November 26 2007
?
Runtime IL injection
Gripper-LOOM.NET
Updated to 0.92 at January 17 2008
?
Compile time IL injection
Relies on Rapier-LOOM.NET
PIAB
Updated to 5.0 at April 2010
Ms-PL
Runtime proxy
Well documented.
Multipurpose framework
LinFu
Updated to 2.3 on January 02, 2011
LGPL V3
Runtime proxy
Out of datedocuments.
Relies on Cecil. Multipurpose framework
heredar
Updated to Alpha 1 on January 31, 2011
?
Static mixins
Relies on Cecil.
Spring.Net
Updated to 1.3.1
Apache 2.0
Runtime proxy
Well documented.
Commercial support and training.
Multipurpose framework
来看几个框架的一些具体介绍
关于几个IL织入的框架
技术上来说,能够支持IL织入的框架是一定能实现AOP的,比如Mono Cecil, MS CCI, MS Phoenix, and Rail。但是由于他们不是专门做AOP的框架,在之后的评比中没有考虑他们。
PIAB
PIAB (The Policy Injection Application Block) 是MS Enterprise Library的一部分。已经内嵌的支持如下aspects
- Authorization
- Exception Handling
- Logging
- Validation
- Performance Counter
- Caching (Caching handler is removed from EntLib 5.0 due to some issues)
Spring.Net
已经内嵌的支持如下aspects。
- Caching
- Exception Handling
- Logging
- Retry
- Transaction Management
- Parameter Validation
Post Sharp
注意Post Sharp对商业应用已不再开源和免费。
以插件的形式支持如下aspects
- Monitoring
- Caching
以插件的形式集成了其他一些著名的框架,但是貌似是Post Sharp 1.5时的事儿了?
最重要的一点:只能inject本assembly中的东西,不能修改其他assembly,这就是为什么我的sample中其他都在调用Models.Tester,唯独Post'Sharp.Interception把Tester的实现copy了一份:要intercept的Buy方法的调用在Tester里。
LinFu
由于PostSharp已经收费,所以就想找一款同样是IL weaving方式的开源AOP框架。目前比较活跃的貌似就属LinFu了,但是实践起来却问题多多(单指AOP方面,这个框架还支持IoC、动态代理等)。比如
文档老旧,很多和最新版(2.3)对不上。
配置上(编辑csproj文件)不支持对指定方法的interception,这是最让人抓狂的,来看
1: <PostWeaveTask TargetFile="$(MSBuildProjectDirectory)\$(OutputPath)$(MSBuildProjectName)$(TargetExt)"
2: InterceptAllExceptions="false"
3: InterceptAllFields="false"
4: InterceptAllNewInstances="false"
5: InterceptAllMethodCalls="true"
6: InterceptAllMethodBodies="false" />
要想inject指定的方法怎么办?实现自己的Task去解析!
另外,我的sample程序也跑不起来,原因不明。。。用MethodBodyReplacement的方法JIT时报错,用AroundMethodCall方法报CLR遇到一个invalid program。。。
评比
前人的一些工作
mono-cecil-vs-postsharp-core-vs-microsoft-cci-for-implementing-aop-framework
5 Sep 2009
Rating of Open Source AOP Frameworks in .NET
5 Aug 2008
主流.Net AOP Framework的功能定位分析
31 Aug 2005
其中第二篇参考意义比较大,感兴趣的不妨去看看,其结论是三甲为PostSharp、PIAB、Spring.Net
本文的评比标准
- 能力上,至少能够inject public方法,不论其是否virtual
- project本身至少要保持更新,且有release版
- 性能与raw的调用不能差太多
参评框架
根据以上标准,选取PostSharp、PIAB、Spring.Net。
性能测试
参评的三个框架每种都用有源代码的情况下和无源代码的情况下两种方式实现,与raw调用进行对比。
测试case为IOder ICustomer.Buy(IProduct product)
每组都实现两个advice
- 输出trace
- 若Customer.WorkingAt = Product.ProducedBy,打八折
raw的实现是这样的
1: public IOrder Buy(IProduct product, int count = 1)
2: {
3: var order = new Order
4: {
5: Count = count,
6: Product = product,
7: Customer = this,
8: UnitPrice = product.UnitPrice
9: };
10:
11: if (WorkingAt.Equals(product.ProduceBy))
12: {
13: order.UnitPrice = product.UnitPrice*0.8;
14: }
15: Console.WriteLine(string.Format("{0} bought {1} at {2}. Count={3}, Unit Price={4}",
16: order.Customer.Name, order.Product.Name, DateTime.Now, order.Count,
17: order.UnitPrice));
18: return order;
19: }
效果如下
测试调用100,200,…1500次,测算每次调用耗费的毫秒数,列表如下
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
1500
Raw
2.33
0.465
0.56
0.55
0.548
0.558333
0.56
0.57125
0.564444
0.548
0.551818
0.55
0.548462
0.552857
0.548
PIAB
2.5
0.665
0.636667
0.6725
0.656
0.651667
0.65
0.6525
0.658889
0.654
0.645455
0.655
0.653077
0.655714
0.652
PIAB.Interception
2.5
0.67
0.66
0.6575
0.652
0.655
0.655714
0.64875
0.655556
0.654
0.654545
0.655833
0.653846
0.655
0.655333
PostSharp
3
0.55
0.553333
0.54
0.55
0.546667
0.548571
0.5575
0.553333
0.553
0.55
0.5525
0.552308
0.555
0.55
PostSharp.Interception
3.15
0.525
0.53
0.5725
0.554
0.561667
0.567143
0.555
0.565556
0.555
0.563636
0.558333
0.56
0.560714
0.558667
Spring
2.44
0.53
0.586667
0.5825
0.578
0.583333
0.574286
0.56375
0.56
0.564
0.553636
0.565
0.563846
0.564286
0.562667
Spring.Interception
2.59
0.52
0.523333
0.5375
0.538
0.548333
0.548571
0.54875
0.547778
0.544
0.553636
0.5475
0.546154
0.547143
0.549333
直观起见,直接上图(去掉了100的那一组数据)
可见PostSharp和Spring.Net都达到了接近Raw的性能,而PIAB仍需努力。
结论
如果喜欢IL织入,选择PostSharp
如果喜欢runtime proxy,选择Spring.Net
最佳实践
最佳实践这个题目对于我来说太大了。只能说是一些网上看来和实践得到的注意事项吧
通用
使用功能上最低限度的advice。例如只在after invoke做一些事的话就尽量不用around invoke的advice。
filed的interception是对OO的侵犯(直接无视了OO的第一条:封装),不要使用(三者中只有PostSharp支持)。
如果你的advice实现了某些特殊功能(而不是logging这种普通的功能),在你的方法上做出说明。
如果你的advice准备对全局起作用,就把它放在一个全局的地方,并且详加说明。
使用AOP时总是会造成一些与预期不同的结果,给你造成很多困扰。如果今后别人接手会给他造成更多的麻烦。所以有时还是用传统的方式吧。
PIAB
我使用EntLibConfig.NET4-32.exe编辑我的app.config,结果怎么都不行,之后删除了parameter节点中的typeName的assembly信息部分就OK了,原因不明。
PostSharp
已经不需要手动修改csproj文件,至少我的例子中没有。
Spring.Net
由于Spring.Net没有像PIAB一样提供一个Wrap方法,所以为了能从Spring容器中取出inject过的对象,还是需要在配置文件中进行配置,然后从ContextRegistry中取。例如本例中的
1: <object id="customer" type="AopInvestigate.Implements.Spring.Models.Customer, AopInvestigate.Implements.Spring" singleton="false"/>
- AOP in .NET
- AOP in Asp.net MVC
- AOP in Asp.net MVC
- The Present AOP Frameworks in .Net
- 什么是AOP? AOP .Net 框架,AOP 资源
- AOP in JavaScript
- Spring AOP in Annotaion
- .NET :消息与AOP
- .Net平台AOP技术研究
- .NET :消息与AOP
- .Net平台AOP技术研究
- .NET :消息与AOP
- .Net平台AOP技术研究
- .Net平台AOP技术研究
- spring.net aop
- .Net平台AOP技术研究
- Spring.Net AOP实例
- .Net平台AOP技术研究
- win10 升级10041:Windows can't be installed because this PC has an unsupported disk layout for UEFI
- request&response笔记
- In-App Purchase 实战总结
- AngularJs之与后端服务器通信
- 美国互联网公司为什么只在中国失败了?
- AOP in .NET
- js正则限制input框输入的常用代码
- 20.allegro.铺铜
- JAVA学习笔记(二十)- 集合 List
- sublime text插件中获取配置参数的方法
- Swift语言iOS开发:CALayer十则示例
- Study Html《div 显示滚动条的CSS代码》
- Ant使用指南
- 《VxWorks学习笔记》——任务属性