上面也给出的简单的分析,下面我们还是结合代码来说说吧,如何来操作:
既然我们要注入到具体的方法中,那么我们通过标记的形式来标记某个方法是要执行注入的目标方法。我们这里定义这个特性的抽象类。
public abstract class DecoratorAttributeBase : Attribute
{
///
/// AOP注入机制
///
///
public abstract void Intercept(object target);
}
我们对于具体的缓存操作,我们定义TimeOutAttribute 个特性,当执行某个方法的时候,我们即刷新缓存。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TimeOutAttribute : DecoratorAttributeBase
{
public override void Intercept(object target)
{
MethodCallMessageWrapper caller = (MethodCallMessageWrapper)target;
if (caller.ArgCount == 0)
return;
//重新设置缓存。
}
}
这里我没有给出具体的缓存过期的代码,如果大家想知道具体的操作缓存的代码,那么大家请参考上篇中的《<a href="http://www.cnblogs.com/hegezhou_hot/archive/2010/09/19/1831256.html">网站性能优化之应用程序缓存-中篇</a>》中的操作缓存的类,
那么我们再来看看具体的配置文件中的格式吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<cacheModels>//缓存的对象列表
<cacheModel id="CacheLRU_Sys_UserRole" implementation="LRU" >//缓存的对象
<flushInterval minutes="2" />//设置过期策略
<flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的动作
<flushOnExecute statement="Update_Sys_UserRole"/>
<flushOnExecute statement="Delete_Sys_UserRole"/>
<property name="CacheSize" value="100"/>//设置缓存对象的大小
</cacheModel>
</cacheModels>
配置具体的缓存刷新动作
<flushOnExecute statement="Insert_Sys_UserRole"/>//刷新的动作
<flushOnExecute statement="Update_Sys_UserRole"/>
<flushOnExecute statement="Delete_Sys_UserRole"/>
下面我们给出具体的通用代理类实现:
public class CustomProxy : RealProxy, IDisposable where T : MarshalByRefObject
{
/// 构造过程中把Proxy需要操作的内容与实际目标对象实例Attach到一起。
public CustomProxy(T target) : base(target.GetType())
{
AttachServer(target);
}
/// 析构过程则借助proxy和目标对象实例的Attach,便于GC回收。
public void Dispose()
{
DetachServer();
}
public static T Create(T target)
{
if (target == null)
throw new ArgumentNullException("target");
return (T)(new CustomProxy(target).GetTransparentProxy());
}
/// 实际执行的拦截,并根据装饰属性进行定制处理。
public override IMessage Invoke(IMessage msg)
{
MethodCallMessageWrapper caller =
new MethodCallMessageWrapper((IMethodCallMessage)msg);
// 提取实际宿主对象
MethodInfo method = (MethodInfo)caller.MethodBase;
T target = (T)GetUnwrappedServer();
DecoratorAttributeBase[] attributes = (DecoratorAttributeBase[])
method.GetCustomAttributes(typeof(DecoratorAttributeBase), true);
object ret = method.Invoke(target, caller.Args);
if (attributes.Length > 0)
foreach (DecoratorAttributeBase attribute in attributes) attribute.Intercept(caller);
// 拦截处理后,继续回到宿主对象的调用过程
return new ReturnMessage(ret, caller.Args, caller.ArgCount,
caller.LogicalCallContext, caller);
}
}
我们这里定义一个基类:
public abstract class Base : MarshalByRefObject
{
//定义相关方法,可以为子类提供相关的其他服务
}
我们来看看具体的实体代码:
class Book : Base
{
private string name;
private string title;
[TimeOut()]
public void SetBookInfo(object name, object title)
{
this.name = (string)name;
this.title = (string)title;
}
}
具体的测试代码如下:
<div class="cnblogs_Highlighter"><pre class="brush:csharp"> Book book= CustomProxy.Create(new Book());
book.SetBookInfo("joe", "manager"); // 成功
try
{
book.SetBookInfo(20, "manager");
}
catch (Exception exception)
{
// 因第一个参数类型异常被拦截后抛出异常
//Assert.AreEqual("0", exception.Message);
}
try
{
book.SetBookInfo("", "manager");
}
catch (Exception exception)
{
// 因name为空被拦截后抛出异常
//Assert.AreEqual("string is null or empty", exception.Message);
}
</pre>
</div>
这样我们就在我们的应用程序中集成了缓存服务,当然还有更好的方式来使用AOP,这里的继承 MarshalByRefObject 限制了我们在程序中使用AOP,必须继承这个类,当然后续我会讲解如何通过
另外的几类实现方案,我们可以对比结合我们的应用框架来无缝集成。
六、本章总结
目前在.Net平台下的AOP大部分仍然处于最初的开发阶段,各自发布的版本基本都是beta版。其中较有代表性的AOP工具包括Aspect#,Spring.Net,Eos等。
Aspect#是基于Castle动态代理技术实现的。Castle动态代理技术利用了.Net的Emit技术,生成一个新的类去实现特定的接口,或者扩展一个已有的类,并将其委托指向IInterceptor接口的实现类。通过Castle动态代理技术,就可以拦截方法的调用,并将Aspect的业务逻辑织入到方法中。利用Castle动态代理技术,最大的缺陷是它只对虚方法有效,这限制了Aspect#的一部分应用。
Spring.Net从根本意义上来说,是对Spring工具从Java平台向.Net平台的完全移植。它在AOP的实现上与Spring几乎完全相似,仍然利用了AOP联盟提供的拦截器、Advice等实现AOP。
Spring.Net的配置文件也与Spring相同。
Eos采用的是静态织入的技术。它提供了独有的编译器,同时还扩展了C#语法,以类似于AspectJ的结构,规定了一套完整的AOP语法,诸如aspect,advice,before,after,pointcut等。
Eos充分的利用了.Net中元数据的特点,以IL级的代码对方面进行织入,这也使得它的性能与其他AOP工具比较有较大的提高。
七、下篇预告
下一篇,我们将会从从spring.NET与EF中的AOP的植入来剖析下,其他的可能的AOP的机制,这样我们能够更深入的了解AOP的技术和实现思路,我们掌握了基本的原理
后,应用它才能够游刃有余。能够更好的控制他,通过AOP能够更方便的让我们将关注度集中在业务层。由于本人水平有限,欢迎大家拍砖,不足之处,还请大家多多指出。
本文转自何戈洲博客园博客,原文链接:http://www.cnblogs.com/hegezhou_hot/archive/2010/12/27/1918121.html,如需转载请自行联系原作者