AOP概念

 

13.1 简介

面向切面编程采用另外一种编程框架完成面向对象编程. 然而,面向对象是把应用程序分解成多层次的对象,而面向切面编程把应用程序分解成各个切面或者说关系面. 切面对关注点进行模块化,例如横切多个类型和对象的事务管理。 (这些关注点术语通常称作横切(crosscutting)关注点。)

Spring.net的一个关键的组件就是 AOP框架。 尽管如此,Spring.net IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring.net IoC容器更加完善。

 

Spring.NET中所使用的AOP:

* 提供声明式企业服务,特别是为了代替COM+声明式企业式服务. 最重要的服务是 声明性事务管理(declarative transaction management) ,这个服务建立在Spring.NET的抽象事务管理(transaction abstraction)之上。

* 允许用户实现自定义的切面,用AOP来完善OOP的使用。

 

这样你可以把Spring.NET AOP看作是一种允许Spring.NET提供声明式事务管理而不必借用COM+的一种授权技术;或者可以充分发挥Spring.NET AOP框架来实现自定义切面.

 

 

13.1.1 AOP概念

       让我们从定义几个最主要的AOP概念开始这方面的内容. 以下这些术语不是Spring.NET技术专有的. 不幸的是,AOP术语并不是特别的直观;如果Spring.NET使用自己的术语,将会问题变得更加令人困惑。

 

*切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是企业级应用(.NET)中一个关于横切关注点的很好的例子。在Spring.NET中,切面可以使用 Advisors 或者 interceptors来实现.

 

*连接点(Joinpoint): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。

 

*通知(Advice):在AOP框架中,通知发生在某些特殊的点上.通知有不同的类型,包括around,before,还有throws.关于通知的类型将会在下面讨论. 许多AOP框架,包括Spring.NET,都是以interceptors(拦截器)做通知模型,并维护一个以连接点为中心的拦截器链。

 

*切入点(Pointcut):匹配连接点(Joinpoint)的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。一个AOP框架必须允许开发者去详细主义自己的切入点,例如,使用常量表达式.

 

*引入(Introduction):增加方法或者字段到一个类. Spring.NET允许你引入新的接口到任何详细定义过的对象.例如,你可以使用引入让所有的对象执行一个Iauditable接口,这样就简化了跟踪一个对象状态的变化情况.

 

*目标对象(Target Object):包含一个连接点的对象.也被称为代理对象.

 

*AOP代理(AOP Proxy):AOP框架产生的对象,包括通知(Advice).在Spring.NET中, AOP代理是一个使用IL代码在运行时产生的动态代理.

 

*织入(Weaving):把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象。这些可以在编译时(例如使用Gripper-Loom.NET编译器),类加载时和运行时完成。Spring.NET在运行时织入.

 

不同类型的通知(Advice):

环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。

 

前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。

抛出通知(Throws advice):当一个方法抛出异常时,这种类型的通知被执行. Spring.NET提供了强而有力的抛出通知,所以你可以编写捕获你所感兴趣的异常的代码,而不必从Exception这个超类转化而来.

 

返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。

 

Spring.NET提供了所有类型的通知, 我们推荐你使用尽量简单的通知类型来实现需要的功能。例如,如果你只是需要用一个方法的返回值来更新缓存,虽然使用环绕通知也能完成同样的事情,但是你最好使用After returning通知而不是环绕通知。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。 比如,你不需要调用 JoinPoint(用于Around Advice)的 proceed() 方法,就不会有调用的问题。

   切入点(pointcut)概念是AOP的关键,这使得能从其它老的仅仅能提供拦截功能技术区别出AOP. 切入点使得定位通知(advice)可独立于OO层次。例如,一个提供声明式事务管理的around通知可以被应用到一组横跨多个对象中的方法上.因此切入点提供了AOP的结构化组件.

 

 

13.1.2 Spring.NET AOP的功能

       Spring.NET AOP用纯C#实现.它不需要专门的编译过程----所有的编入都会在运行时完成. Spring.NET AOP不需要控制或者修改装载器的的加载方式,它也不需要依靠没有完成的API,所以它适合在CLR环境中使用.

       Spring.NET目前仅支持方法调用拦截,还不支持字段拦截,但增加字段拦截也不会破坏Spring.NET AOP APIs的代码.

       Spring.NET provides提供了表示切入点和各种通知的类. Spring.NET 为一个表示切面的对象使用术语顾问 (advisor),包括一个通知和一个指向特定连接点的切入点.

       不同的通知类型是ImethodInterceptor(这个接口来自AOP联盟的拦截API),而通知的所有接口定义在Spring.Aop名字空间里.所有的通知必须实现AopAlliance.Aop.Iadvice标签接口.通知支持它的包装是IMethodInterceptor ; IThrowsAdvice; IBeforeAdvice; 还有 IAfterReturningAdvice..关于通知更详细的内容我们将会在下面讲到.

       Spring.NET还提供了一个由AOP 联盟定义的JAVA接口的.NET转换.环形通知必须实现AOP联盟的AopAlliance.Interceptr.IMethodInterceptor接口.同时,在JAVA领域,也为AOP 联盟提供了广泛的支持, Spring.NET目前只适用于利用这些接口的.NET AOP 框架.就目前来说,这将会为同时在.NET和JAVA领域中搞开发的开发者提供一个协调的编程模型, 从更长远的发展来看,我们当然希望看见更多的.NET 项目适应AOP联盟(AOP Alliance)的接口.

       Spring.NET AOP从来没有打算通过提供一种全面的AOP解决方案来取代AspectJ. 然而, Spring.NET为许多顺从于AOP 的.NET应用提供了一套优秀的解决方案.

       所有,看到Spring.NET AOP的功能跟Spring.NET IoC container一起协调使用你也不会再感到惊讶了.AOP用跟普通对象定义一样的语法来详细说明;通知和切入点由Spring.NET IoC实现自己的管理.

 

13.1.3 Spring.NET 的AOP代理

       Spring.NET使用系统的类在运行时产生代理. Reflection.Emit名字空间为代理的类产生IL代码.这样就能产生很有效益的代理,并且这些代理不会对继承的层次关系施加任何限制.

       另外一种常见的实现代理的方法是使用ContextBoundObject对象和.NET远程架构作为拦截机制.我们对使用ContextBoundObject这种方法不是很提倡,因为它需要直接或者间接继承于ContextBoundObject的类被当作代理.依我们看来,使你的类继承于第三访会使你的应用很难控制.而且这种机制产生的Context-bound代理也会比第一种方法产生的代理会由于上下文交换和远程架构而速度慢很多.

       Spring.NET AOP代理也是很轻巧的----这是由于代理的配置在代理产生的时候已经知道了,产生的代理如果有必要的话能够通过映射来调用目标方法而来优化自己(比如说,有通知应用于目标方法时).在其它的事例中,目标方法被直接地调用,这样就避免了执行冲突.

       最后, Spring.NET AOP代理永远不会返回一个没有经过任何未知的引用给目标对象.无论何时,如果目标方法返回一个未知的引用给一个目标对象,AOP代理会马上意识到发生了什么事,并会用自己的引用来取代这个返回的未知的引用.

       目前,产生代理的实现方式使用了对象的组合来代表代理到目标对象的请求,这跟你怎样实现一个Decorator模式很相似.这意味着要被作为代理的类必须实现一个或者更多的接口,这种方法将会比使用ContextBoundObject方法更少的聚合要求.

 

 

 

 

 

 

 

 

13.2 Spring.NET AOP API

       让我们看看Spring.NET怎样操作切入点这个重要概念的.

13.2.1 概念

 

       Spring.NET的切入点模型使得切入点可以独立于通知类型进行重用,这就使得针对不同通知( advice)使用相同的切入点(pointcut)成为可能。

       Spring.Aop.Ipointcut是最核心的接口.用来将通知应用于特定的类和方法.这个接口的完整定义如下:

        public interface IPointcut 
         { 
          ITypeFilter TypeFilter { get; } 
           IMethodMatcher MethodMatcher { get; } 
         } 

IPointcut接口分割成有利于重用类型和方法匹配的两部分, 以及进行更细粒度的操作组合(例如与另一个方法匹配实现进行“或操作”)。

       ItypeFilter接口用来将切入点限制在一个给定的类集合里面. 如果matches()方法总是返回true,所有目标类都将被匹配:

       public interface ITypeFilter

{

           bool Matches(Type type);

}

 

       ImethodMatcher接口通常更重要,这个接口的完整定义如下:

       public interface IMethodMatcher

{

           bool IsRuntime { get; }

bool Matches(MethodInfo method, Type targetType);

bool Matches(MethodInfo method, Type targetType, object[] args);

}

       Matches(MethodInfo, Type)方法用来测试这个切入点是否匹配目标类的指定方法。这将在AOP代理被创建的时候执行,这样可以避免在每次方法调用的时候都执行。如果两个参数的matches方法对于一个给定的方法返回true并且IMethodMatcher接口的IsRuntime方法也返回true,那么有三个参数的matches方法将在每个方法调用时被调用. 这使得切入点在通知将被执行前可以查看传入到方法的参数。

       绝大多数的IMethodMatcher接口是static,这也就意味着它们的IsRuntime属性返回false.在这种情况下,有三个参数的Matches方法将永远不会被调用.

提示

应尽可能地使切入点是静态的,这就允许AOP框架在AOP代理被创建时缓存对切入点的计算结果。

 

13.2.2 在切入点上的操作

       Spring.NET支持在切入点上的操作有:或和与

       * 或运算表示只需有一个切入点被匹配就执行方法。

* 与运算表示所有的切入点都匹配的情况下才执行。

* 通常或运算要更有用一些。

 

   切入点能使用Spring.Aop.Support.Pointcuts类中的的静态方法来编写,或者使用同一个包内的ComposablePointcut.

13.2.3 便利的切入点实现

       Spring.NET提供了一些很方便的切入点实现.一些是开箱即用的, 其它的是切入点应用规范的子集。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值