EsbAOP是EnterpriseServerBase类库中的轻量级AOP框架,它实现了AOP的主要思想--对方法调用进行截获,并加入自定义的预处理、后处理。 EsbAOP与其它很多开源的AOP实现有些不同,其不同之处主要在于EsbAOP并没有严格的实现AOP理论的各种设施,但是EsbAOP非常实用,在后续的文章中,大家可以看到EsbAOP是如何运用于实际的系统开发中的。
理解EsbAOP系列文章需要Remoting和消息方面的知识作为基础,如果你以前没有接触过这些内容,可以阅读《.NET 本质论》的第七章。下面就来开始我们的EsbAOP之旅吧。
既然AOP的核心思想是对方法调用进行截获,并加入自定义的预处理、后处理,那么我们可以很直观的定义出IAspect(方面)接口。而“特定方面”就是实现了IAspect接口的类,什么是“特定方面”?“特定方面”就是完成某一特定目的的一个Aspect,比如权限方面的特定目的就是进行权限管理。即,一个特定的方面,就代表了一个特定目的的前处理和后处理!
其中参数requestMsg表示方法调用的请求消息,而respond表示方法调用的结果。注意,如果目标方法在运行的过程中抛出了一个异常,那么该异常也表现为一个IMethodReturnMessage消息。注意,respond参数加上了ref关键字,表示EsbAOP不仅可以截获方法调用,而且还能改变方法运行的结果,这是多么神奇的功能啊!
另外还有两个参数aspectClassArgument和aspectMethodArgument,为了更方便地说明它们的作用,非得举个例子不可,如下一个应用权限Aspect的例子。
看了这段描述,不知道你对这两个参数有点了解了没有,不是太明白也没关系,对它们的认识后面会慢慢清晰起来的。
上面Example类上用的“Aspect”特性,这个特性的定义如下:
可以看到,该特性的主要任务是把目标实例委托给AspectChainProxy代理,使截获方法调用得以顺利切入!AspectAttribute的构造参数由params修饰,表示其可接受多个参数,每一个参数对应这一个特定目的的方面(最终,AspectAttribute把这些参数传给了AspectChainProxy代理),这表示前面的例子中可以这样:
AspectChainProxy代理用于管理所有运用于目标类(如上面的Example类)上的所有方面,使在运行时,CLR能调用所有方面的前处理和后处理,AspectChainProxy实现如下:
AspectChainProxy的第四个构造参数正是从AspectAttribute传递过来的,这个参数包含了运用于目标类的所有特定方面的相关信息。AspectChainProxy的核心方法是Invoke方法,该方法由CLR在进入截获阶段时调用。Invoke方法的流程一目了然。
上文已经有几个地方已经涉及了IAspectProcessorWrap接口了,正如其名,它是一个包装,包装中的主要内容是一个Asepect,以及提供与该Aspect相关的其它信息。
注释已经很好的解释了IAspectProcessorWrap接口的方方面面,到这里,你也许发现了,AspectAttribute的构造参数就是实现了IAspectProcessorWrap的类型。一个特定目的方面(如PermissionAspect)就对应着一个包装(PermissionAspectWrap)。
关于这个轻量级的AOP实现,还有一个基础设施没有介绍,那就是AspectSwitcherAttribute,这也是一个特性,主要用于修饰方法。它的目的有两个:
(1)决定被修饰方法针对某特定方面是否启用截获。比如当Example类上使用权限Aspect时,对每个方法的调用都将进行权限判断,然而有些方法调用可能是不需要权限判断的,这种一锅端的做法存在很多AOP实现中,而EsbAOP通过AspectSwitcherAttribute很好的解决了这个问题。并且,IAspectProcessorWrap接口的DefaultAspectSwitcherState属性更是对此支持的增强。
(2)传递前述的aspectMethodArgument给预处理和后处理。这个前面已经见过了。
AspectSwitcherAttribute的定义如下:
EsbAOP的所有实现就介绍完了,如果讲述有不清楚的地方,请留言,我会根据反馈进行修改。在后续的文章中,将在EsbAOP的基础上开展AOP应用,比如权限管理、异常日志、异常关闭器......。
理解EsbAOP系列文章需要Remoting和消息方面的知识作为基础,如果你以前没有接触过这些内容,可以阅读《.NET 本质论》的第七章。下面就来开始我们的EsbAOP之旅吧。
既然AOP的核心思想是对方法调用进行截获,并加入自定义的预处理、后处理,那么我们可以很直观的定义出IAspect(方面)接口。而“特定方面”就是实现了IAspect接口的类,什么是“特定方面”?“特定方面”就是完成某一特定目的的一个Aspect,比如权限方面的特定目的就是进行权限管理。即,一个特定的方面,就代表了一个特定目的的前处理和后处理!
publicinterfaceIAspect
{
voidPreProcess(IMethodCallMessagerequestMsg,objectaspectClassArgument,objectaspectMethodArgument);
voidPostProcess(IMethodCallMessagerequestMsg,refIMethodReturnMessagerespond,objectaspectClassArgument,objectaspectMethodArgument);
}
{
voidPreProcess(IMethodCallMessagerequestMsg,objectaspectClassArgument,objectaspectMethodArgument);
voidPostProcess(IMethodCallMessagerequestMsg,refIMethodReturnMessagerespond,objectaspectClassArgument,objectaspectMethodArgument);
}
其中参数requestMsg表示方法调用的请求消息,而respond表示方法调用的结果。注意,如果目标方法在运行的过程中抛出了一个异常,那么该异常也表现为一个IMethodReturnMessage消息。注意,respond参数加上了ref关键字,表示EsbAOP不仅可以截获方法调用,而且还能改变方法运行的结果,这是多么神奇的功能啊!
另外还有两个参数aspectClassArgument和aspectMethodArgument,为了更方便地说明它们的作用,非得举个例子不可,如下一个应用权限Aspect的例子。
[Aspect(typeof(PermissionAspectWrap))]
publicclassExample:ContextBoundObject
{
[AspectSwitcher(typeof(PermissionAspectWrap),true,Permission.Super)]
publicvoidSayHello(stringname)
{
Console.WriteLine("Hello,"+name);
}
}
方法上有个AspectSwitcher特性,它的第三个参数就是aspectMethodArgument。在本例中,这个参数规定了调用SayHello方法所需要的权限是Super。而aspectClassArgument参数位于PermissionAspectWrap的包装之中,它主要用于特定的方面(本例中是PermissionAspect)在执行预处理/后处理时所需要的设施,比如本例中,PermissionAspect就需要通过aspectClassArgument传入一个IPermissionVerifier引用,这个IPermissionVerifier用于对权限是否满足进行判断。publicclassExample:ContextBoundObject
{
[AspectSwitcher(typeof(PermissionAspectWrap),true,Permission.Super)]
publicvoidSayHello(stringname)
{
Console.WriteLine("Hello,"+name);
}
}
看了这段描述,不知道你对这两个参数有点了解了没有,不是太明白也没关系,对它们的认识后面会慢慢清晰起来的。
上面Example类上用的“Aspect”特性,这个特性的定义如下:
///<summary>
///AspectAttribute把被修饰类的实例委托给代理AspectChainProxy,如此可以截获被修饰类的方法调用
///</summary>
[AttributeUsage(AttributeTargets.Class,AllowMultiple=false)]
publicclassAspectAttribute:ProxyAttribute
{
privateType[]theAspectProcessorWrapTypes=null;
publicAspectAttribute(paramsType[]wrapTypes)
{
this.theAspectProcessorWrapTypes=wrapTypes;
}
#regionCreateInstance
///<summary>
///获得目标对象的自定义透明代理,该方法由系统调用
///</summary>
publicoverrideMarshalByRefObjectCreateInstance(TypeserverType)//serverType是被AopProxyAttribute修饰的类
{
//未初始化的实例的默认透明代理
MarshalByRefObjecttarget=base.CreateInstance(serverType);//得到未初始化的实例(ctor未执行)
object[]args={target,serverType};
//得到自定义的真实代理
RealProxyrp=newAspectChainProxy(target,serverType,this.theAspectProcessorWrapTypes);//newAopControlProxy(target,serverType);
return(MarshalByRefObject)rp.GetTransparentProxy();
}
#endregion
}
///AspectAttribute把被修饰类的实例委托给代理AspectChainProxy,如此可以截获被修饰类的方法调用
///</summary>
[AttributeUsage(AttributeTargets.Class,AllowMultiple=false)]
publicclassAspectAttribute:ProxyAttribute
{
privateType[]theAspectProcessorWrapTypes=null;
publicAspectAttribute(paramsType[]wrapTypes)
{
this.theAspectProcessorWrapTypes=wrapTypes;
}
#regionCreateInstance
///<summary>
///获得目标对象的自定义透明代理,该方法由系统调用
///</summary>
publicoverrideMarshalByRefObjectCreateInstance(TypeserverType)//serverType是被AopProxyAttribute修饰的类
{
//未初始化的实例的默认透明代理
MarshalByRefObjecttarget=base.CreateInstance(serverType);//得到未初始化的实例(ctor未执行)
object[]args={target,serverType};
//得到自定义的真实代理
RealProxyrp=newAspectChainProxy(target,serverType,this.theAspectProcessorWrapTypes);//newAopControlProxy(target,serverType);
return(MarshalByRefObject)rp.GetTransparentProxy();
}
#endregion
}
可以看到,该特性的主要任务是把目标实例委托给AspectChainProxy代理,使截获方法调用得以顺利切入!AspectAttribute的构造参数由params修饰,表示其可接受多个参数,每一个参数对应这一个特定目的的方面(最终,AspectAttribute把这些参数传给了AspectChainProxy代理),这表示前面的例子中可以这样:
[AspectAttribute(typeof(PermissionAspectWrap),typeof(ExceptionLoggerAspectWrap))]
publicclassExample:ContextBoundObject
这样就在Example类上运用了两个方面,一个用于权限管理,一个用于异常日志。publicclassExample:ContextBoundObject
AspectChainProxy代理用于管理所有运用于目标类(如上面的Example类)上的所有方面,使在运行时,CLR能调用所有方面的前处理和后处理,AspectChainProxy实现如下:
publicclassAspectChainProxy:RealProxy
{
privateMarshalByRefObjecttarget=null;
privateType[]theAspectProcessorWrapTypes=null;
privateArrayListaspectCallerList=newArrayList();//集合中为AspectCaller实例
publicAspectChainProxy(MarshalByRefObjecttarget,TypeserverType,paramsType[]aopProcessorWrapTypes):base(serverType)
{
this.target=target;
this.theAspectProcessorWrapTypes=aopProcessorWrapTypes;
}
#regionInvoke
publicoverrideIMessageInvoke(IMessagemsg)
{
IMethodCallMessagecall=(IMethodCallMessage)msg;
this.FillAspectCallerList(call);
//如果触发的是构造函数,此时target的构建还未开始
IConstructionCallMessagector=callasIConstructionCallMessage;
if(ctor!=null)
{
//获取最底层的默认真实代理
RealProxydefault_proxy=RemotingServices.GetRealProxy(this.target);
default_proxy.InitializeServerObject(ctor);
MarshalByRefObjecttp=(MarshalByRefObject)this.GetTransparentProxy();//自定义的透明代理this
returnEnterpriseServicesHelper.CreateConstructionReturnMessage(ctor,tp);
}
this.PreProcess(call);
IMethodReturnMessageresult_msg=RemotingServices.ExecuteMessage(this.target,call);//将消息转化为堆栈,并执行目标方法,方法完成后,再将堆栈转化为消息
this.PostProcess(call,refresult_msg);
returnresult_msg;
}
#endregion
#regionFillAspectCallerList
privatevoidFillAspectCallerList(IMethodCallMessagecall)
{
this.aspectCallerList.Clear();
if(this.theAspectProcessorWrapTypes==null)
{
return;
}
//显式启动了方面的WrapType
ArrayListovertWrapTypeList=newArrayList();
//查询目标方法是否"显式"启用AOP的MethodAopSwitcherAttribute
foreach(Attributeattrincall.MethodBase.GetCustomAttributes(false))
{
AspectSwitcherAttributeaspectSwitcher=attrasAspectSwitcherAttribute;
if(aspectSwitcher==null)
{
continue;
}
if(aspectSwitcher.DestAspectProcessorWrapType==null)
{
continue;
}
overtWrapTypeList.Add(aspectSwitcher.DestAspectProcessorWrapType);
if(!aspectSwitcher.UseAspect)
{
continue;
}
IAspectProcessorWrapprocessorWrap=this.GetAspectProcessorWrap(aspectSwitcher.DestAspectProcessorWrapType);
if(processorWrap==null)
{
continue;
}
AspectCallercaller=newAspectCaller();
caller.AspectMethodArgument=aspectSwitcher.AopArgument;
caller.CurProcessorWrap=processorWrap;
this.aspectCallerList.Add(caller);
}
//非显式启用的方面
foreach(TypewrapTypeinthis.theAspectProcessorWrapTypes)
{
boolpassIt=this.WrapTypeIsInOvertWrapTypeList(wrapType,overtWrapTypeList);
if(!passIt)
{
IAspectProcessorWrapprocessorWrap=(IAspectProcessorWrap)Activator.CreateInstance(wrapType);
if(processorWrap.DefaultAspectSwitcherState==AspectSwitcherState.On)
{
AspectCallercaller=newAspectCaller();
caller.CurProcessorWrap=processorWrap;
this.aspectCallerList.Add(caller);
}
}
}
}
privateboolWrapTypeIsInOvertWrapTypeList(TypewrapType,ArrayListovertWrapTypeList)
{
foreach(TypetempWrapTypeinovertWrapTypeList)
{
if(wrapType==tempWrapType)
{
returntrue;
}
}
returnfalse;
}
#endregion
#regionGetAspectProcessorWrap
privateIAspectProcessorWrapGetAspectProcessorWrap(TypeaspectProcesserWrapType)
{
foreach(TypewrapTypeinthis.theAspectProcessorWrapTypes)
{
if(wrapType==aspectProcesserWrapType)
{
IAspectProcessorWrapwrap=(IAspectProcessorWrap)Activator.CreateInstance(wrapType);
returnwrap;
}
}
returnnull;
}
#endregion
#regionPreProcess,PostProcess
privatevoidPreProcess(IMethodCallMessagerequestMsg)
{
foreach(AspectCallercallerinthis.aspectCallerList)
{
IAspectaspectProcessor=(IAspect)Activator.CreateInstance(caller.CurProcessorWrap.AspectProcessorType);
if(aspectProcessor!=null)
{
aspectProcessor.PreProcess(requestMsg,caller.CurProcessorWrap.AspectClassArgument,caller.AspectMethodArgument);
}
}
}
privatevoidPostProcess(IMethodCallMessagerequestMsg,refIMethodReturnMessagerespond)
{
foreach(AspectCallercallerinthis.aspectCallerList)
{
IAspectaspectProcessor=(IAspect)Activator.CreateInstance(caller.CurProcessorWrap.AspectProcessorType);
if(aspectProcessor!=null)
{
aspectProcessor.PostProcess(requestMsg,refrespond,caller.CurProcessorWrap.AspectClassArgument,caller.AspectMethodArgument);
}
}
}
#endregion
}
///<summary>
///AspectCaller针对某一特定的方法,实施的一次Aspect调用
///</summary>
publicclassAspectCaller
{
publicIAspectProcessorWrapCurProcessorWrap=null;
publicobjectAspectMethodArgument=null;
}
{
privateMarshalByRefObjecttarget=null;
privateType[]theAspectProcessorWrapTypes=null;
privateArrayListaspectCallerList=newArrayList();//集合中为AspectCaller实例
publicAspectChainProxy(MarshalByRefObjecttarget,TypeserverType,paramsType[]aopProcessorWrapTypes):base(serverType)
{
this.target=target;
this.theAspectProcessorWrapTypes=aopProcessorWrapTypes;
}
#regionInvoke
publicoverrideIMessageInvoke(IMessagemsg)
{
IMethodCallMessagecall=(IMethodCallMessage)msg;
this.FillAspectCallerList(call);
//如果触发的是构造函数,此时target的构建还未开始
IConstructionCallMessagector=callasIConstructionCallMessage;
if(ctor!=null)
{
//获取最底层的默认真实代理
RealProxydefault_proxy=RemotingServices.GetRealProxy(this.target);
default_proxy.InitializeServerObject(ctor);
MarshalByRefObjecttp=(MarshalByRefObject)this.GetTransparentProxy();//自定义的透明代理this
returnEnterpriseServicesHelper.CreateConstructionReturnMessage(ctor,tp);
}
this.PreProcess(call);
IMethodReturnMessageresult_msg=RemotingServices.ExecuteMessage(this.target,call);//将消息转化为堆栈,并执行目标方法,方法完成后,再将堆栈转化为消息
this.PostProcess(call,refresult_msg);
returnresult_msg;
}
#endregion
#regionFillAspectCallerList
privatevoidFillAspectCallerList(IMethodCallMessagecall)
{
this.aspectCallerList.Clear();
if(this.theAspectProcessorWrapTypes==null)
{
return;
}
//显式启动了方面的WrapType
ArrayListovertWrapTypeList=newArrayList();
//查询目标方法是否"显式"启用AOP的MethodAopSwitcherAttribute
foreach(Attributeattrincall.MethodBase.GetCustomAttributes(false))
{
AspectSwitcherAttributeaspectSwitcher=attrasAspectSwitcherAttribute;
if(aspectSwitcher==null)
{
continue;
}
if(aspectSwitcher.DestAspectProcessorWrapType==null)
{
continue;
}
overtWrapTypeList.Add(aspectSwitcher.DestAspectProcessorWrapType);
if(!aspectSwitcher.UseAspect)
{
continue;
}
IAspectProcessorWrapprocessorWrap=this.GetAspectProcessorWrap(aspectSwitcher.DestAspectProcessorWrapType);
if(processorWrap==null)
{
continue;
}
AspectCallercaller=newAspectCaller();
caller.AspectMethodArgument=aspectSwitcher.AopArgument;
caller.CurProcessorWrap=processorWrap;
this.aspectCallerList.Add(caller);
}
//非显式启用的方面
foreach(TypewrapTypeinthis.theAspectProcessorWrapTypes)
{
boolpassIt=this.WrapTypeIsInOvertWrapTypeList(wrapType,overtWrapTypeList);
if(!passIt)
{
IAspectProcessorWrapprocessorWrap=(IAspectProcessorWrap)Activator.CreateInstance(wrapType);
if(processorWrap.DefaultAspectSwitcherState==AspectSwitcherState.On)
{
AspectCallercaller=newAspectCaller();
caller.CurProcessorWrap=processorWrap;
this.aspectCallerList.Add(caller);
}
}
}
}
privateboolWrapTypeIsInOvertWrapTypeList(TypewrapType,ArrayListovertWrapTypeList)
{
foreach(TypetempWrapTypeinovertWrapTypeList)
{
if(wrapType==tempWrapType)
{
returntrue;
}
}
returnfalse;
}
#endregion
#regionGetAspectProcessorWrap
privateIAspectProcessorWrapGetAspectProcessorWrap(TypeaspectProcesserWrapType)
{
foreach(TypewrapTypeinthis.theAspectProcessorWrapTypes)
{
if(wrapType==aspectProcesserWrapType)
{
IAspectProcessorWrapwrap=(IAspectProcessorWrap)Activator.CreateInstance(wrapType);
returnwrap;
}
}
returnnull;
}
#endregion
#regionPreProcess,PostProcess
privatevoidPreProcess(IMethodCallMessagerequestMsg)
{
foreach(AspectCallercallerinthis.aspectCallerList)
{
IAspectaspectProcessor=(IAspect)Activator.CreateInstance(caller.CurProcessorWrap.AspectProcessorType);
if(aspectProcessor!=null)
{
aspectProcessor.PreProcess(requestMsg,caller.CurProcessorWrap.AspectClassArgument,caller.AspectMethodArgument);
}
}
}
privatevoidPostProcess(IMethodCallMessagerequestMsg,refIMethodReturnMessagerespond)
{
foreach(AspectCallercallerinthis.aspectCallerList)
{
IAspectaspectProcessor=(IAspect)Activator.CreateInstance(caller.CurProcessorWrap.AspectProcessorType);
if(aspectProcessor!=null)
{
aspectProcessor.PostProcess(requestMsg,refrespond,caller.CurProcessorWrap.AspectClassArgument,caller.AspectMethodArgument);
}
}
}
#endregion
}
///<summary>
///AspectCaller针对某一特定的方法,实施的一次Aspect调用
///</summary>
publicclassAspectCaller
{
publicIAspectProcessorWrapCurProcessorWrap=null;
publicobjectAspectMethodArgument=null;
}
AspectChainProxy的第四个构造参数正是从AspectAttribute传递过来的,这个参数包含了运用于目标类的所有特定方面的相关信息。AspectChainProxy的核心方法是Invoke方法,该方法由CLR在进入截获阶段时调用。Invoke方法的流程一目了然。
上文已经有几个地方已经涉及了IAspectProcessorWrap接口了,正如其名,它是一个包装,包装中的主要内容是一个Asepect,以及提供与该Aspect相关的其它信息。
///<summary>
///IAspectProcessorWrap对某一Aspect类型和对应的AspectClassArgument进行封装
///</summary>
publicinterfaceIAspectProcessorWrap
{
TypeAspectProcessorType{get;}//返回的是IAspect的实现
objectAspectClassArgument{get;}
///<summary>
///当一个方法没有被某个方面的AspectSwitcherAttribute修饰时,是否启用该方面
///</summary>
AspectSwitcherStateDefaultAspectSwitcherState{get;}
}
///IAspectProcessorWrap对某一Aspect类型和对应的AspectClassArgument进行封装
///</summary>
publicinterfaceIAspectProcessorWrap
{
TypeAspectProcessorType{get;}//返回的是IAspect的实现
objectAspectClassArgument{get;}
///<summary>
///当一个方法没有被某个方面的AspectSwitcherAttribute修饰时,是否启用该方面
///</summary>
AspectSwitcherStateDefaultAspectSwitcherState{get;}
}
注释已经很好的解释了IAspectProcessorWrap接口的方方面面,到这里,你也许发现了,AspectAttribute的构造参数就是实现了IAspectProcessorWrap的类型。一个特定目的方面(如PermissionAspect)就对应着一个包装(PermissionAspectWrap)。
关于这个轻量级的AOP实现,还有一个基础设施没有介绍,那就是AspectSwitcherAttribute,这也是一个特性,主要用于修饰方法。它的目的有两个:
(1)决定被修饰方法针对某特定方面是否启用截获。比如当Example类上使用权限Aspect时,对每个方法的调用都将进行权限判断,然而有些方法调用可能是不需要权限判断的,这种一锅端的做法存在很多AOP实现中,而EsbAOP通过AspectSwitcherAttribute很好的解决了这个问题。并且,IAspectProcessorWrap接口的DefaultAspectSwitcherState属性更是对此支持的增强。
(2)传递前述的aspectMethodArgument给预处理和后处理。这个前面已经见过了。
AspectSwitcherAttribute的定义如下:
[AttributeUsage(AttributeTargets.Method,AllowMultiple=true)]
publicclassAspectSwitcherAttribute:Attribute
{
privatebooluseAspect=false;
privateobjecttheAopArgument=null;
privateTypedestAspectProcessorWrapType=null;
publicAspectSwitcherAttribute(TypedestAspectWrapType,booluseAop)
{
this.destAspectProcessorWrapType=destAspectWrapType;
this.useAspect=useAop;
}
publicAspectSwitcherAttribute(TypedestAspectWrapType,booluseAop,objectaopArg)
{
this.useAspect=useAop;
this.theAopArgument=aopArg;
this.destAspectProcessorWrapType=destAspectWrapType;
}
publicboolUseAspect
{
get
{
returnthis.useAspect;
}
}
publicobjectAopArgument
{
get
{
returnthis.theAopArgument;
}
}
publicTypeDestAspectProcessorWrapType
{
get
{
returnthis.destAspectProcessorWrapType;
}
}
}
publicenumAspectSwitcherState
{
On,Off
}
publicclassAspectSwitcherAttribute:Attribute
{
privatebooluseAspect=false;
privateobjecttheAopArgument=null;
privateTypedestAspectProcessorWrapType=null;
publicAspectSwitcherAttribute(TypedestAspectWrapType,booluseAop)
{
this.destAspectProcessorWrapType=destAspectWrapType;
this.useAspect=useAop;
}
publicAspectSwitcherAttribute(TypedestAspectWrapType,booluseAop,objectaopArg)
{
this.useAspect=useAop;
this.theAopArgument=aopArg;
this.destAspectProcessorWrapType=destAspectWrapType;
}
publicboolUseAspect
{
get
{
returnthis.useAspect;
}
}
publicobjectAopArgument
{
get
{
returnthis.theAopArgument;
}
}
publicTypeDestAspectProcessorWrapType
{
get
{
returnthis.destAspectProcessorWrapType;
}
}
}
publicenumAspectSwitcherState
{
On,Off
}
EsbAOP的所有实现就介绍完了,如果讲述有不清楚的地方,请留言,我会根据反馈进行修改。在后续的文章中,将在EsbAOP的基础上开展AOP应用,比如权限管理、异常日志、异常关闭器......。
本文介绍了EnterpriseServerBase类库中的轻量级AOP框架EsbAOP,它能截获方法调用并加入自定义处理。文中定义了IAspect接口,介绍了相关特性如Aspect、AspectSwitcherAttribute,还阐述了AspectChainProxy代理的实现,后续将开展权限管理等AOP应用。
159

被折叠的 条评论
为什么被折叠?



