分享

Spring.NET 中的 AOP

 A_POST 2013-05-04

Spring.NET 中的 AOP

AOP 术语

通知(Advice): 通知描述了切面要完成的任务,同时还描述了何时执行这个任务。

连接点(Joinpoint):  程序中应用通知的地方称为连接点,这个点可以是方法被调用时,异常抛出时,甚至访问属性的时候。

切入点(Pointcut): 切入点定义通知切入的一个或者多个连接点。

切面(Aspect): 切面就是通知和切入点的结合。通知和切入点共同定义了切面的全部内容:功能、时机、位置。

引入(Introduction): 允许我们想现有类中增加属性和方法.

目标(Target): 被通知的对象

代理(Porxy): 向目标对象增加通知之后,创建的对象,由这个对象来访问实际的目标对象。

织入(Weaving): 被切面应用到目标对象来创建新的代理对象的过程。

Spring 对 AOP 的支持

Spring.NET 直接使用 C# 来编写通知。

Spring.NET 在运行时进行通知。

Sprint 支持方法的连接点

Spring.NET 使用标记接口 AopAlliance.Aop.IAdvice 来定义通知,这个接口又有四个直接的派生接口,还有两个间接地派生接口。

Spring.Aop.IAfterReturningAdvice,定义方法执行之后的通知,通知的方法名为 AfterReturning

Spring.Aop.IBeforeAdvice,定义所有的前置通知,还是一个标记接口

Spring.Aop.IMethodBeforeAdvice,方法的前置通知接口,通知的方法名称为 Before

AopAlliance.Intercept.IInterceptor, 环绕通知的接口,也是一个标记接口

AopAlliance.Intercept.IMethodInterceptor,方法的环绕通知接口,Invoke 是调用方法。

Spring.Aop.IThrowsAdvice,异常的通知方法,是一个标记接口,但是,实现类中必须存在一个名为 AfterThrowing 的方法,方法可以有任意的返回类型。系统其实是通过反射来调用这个方法的。

这个方法的签名如下:

public void AfterThrowing(Exception ex)

下面的例子来自 Spring In Action ,这里使用 C# 在 Spring.NET 中实现

首先是骑士的接口,切入点必须通过接口实现。

// 定义被代理方法的接口
public interface IKnight
{
String Name { set; get; }
HolyGrail embarkOnQuest();
}

然后,是骑士的定义,这里实现了这个接口。

复制代码
// 被代理的方法必须通过接口实现
public class KnightOfTheRoundTable
: IKnight
{
public String Name { set; get; }
public IQuest Quest { set; get; }

public HolyGrail embarkOnQuest()
{
return Quest.Embark();
}
}
复制代码

诗人的定义

复制代码
// 一个行吟诗人
public class Minstrel
{
public void singBefore(IKnight knight)
{
Console.WriteLine("Fa la la; Sir " + knight.Name + " is so brave!");
}
public void singAfter(IKnight knight)
{
Console.WriteLine("Tee-hee-he; Sir " + knight.Name + " did embark on a quest!");
}
}
复制代码

通知者,这里使用环绕通知。

复制代码
// 每个类只能实现一个接口
public class Advisor :
AopAlliance.Intercept.IMethodInterceptor // 使用环绕通知
{
public Minstrel Minstrel { set; get; }

public object Invoke(AopAlliance.Intercept.IMethodInvocation invocation)
{
IKnight knight = invocation.Target as IKnight; // 取得骑士
this.Minstrel.singBefore(knight); // 前置通知
object result = invocation.Proceed();
this.Minstrel.singAfter(knight); // 后置通知

return result;
}
}
复制代码

其他的辅助类定义,任务等等。

复制代码
public interface IQuest
{
HolyGrail Embark();
}

public class HolyGrailQuest
: IQuest
{
public HolyGrail Embark()
{
Console.WriteLine("探险任务中......");
return new HolyGrail();
}
}
复制代码

在配置文件中,进行切入。

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www." xmlns:aop="http://www./aop">

<!-- 任务 -->
<object id="quest" type="AOP_2.HolyGrailQuest" singleton="true"></object>

<!-- 骑士 -->
<object id="knight" type="AOP_2.KnightOfTheRoundTable" dependency-check="all">
<property name="Quest" ref="quest"></property>
<property name="Name" value="Smith"></property>
</object>

<!--诗人-->
<object id="minstrel" type="AOP_2.Minstrel"/>

<!--通知-->

<!-- 环绕通知,通知的类型由定义的类型确定 -->
<object id="advisor" type="AOP_2.Advisor">
<property name="Minstrel" ref="minstrel"></property>
</object>

<!--定义切入点-->
<object id="pointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="pattern" value="AOP_2.KnightOfTheRoundTable.embarkOnQuest"/>
</object>

<!--切面-->
<aop:config>
<aop:advisor pointcut-ref="pointcut" advice-ref="advisor"/>
</aop:config>

</objects>
复制代码

控制台的主程序。

Spring.Context.IApplicationContext context
= new Spring.Context.Support.XmlApplicationContext("objects.xml");

IKnight knight = context.GetObject("knight")
as IKnight;
knight.embarkOnQuest();

完整代码下载:点击下载

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多