关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-切入点(pointcut)API
本文翻译自Spring.NET官方文档Version 1.3.2。
受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助。
侵删。
让我们看看 Spring.NET 如何处理一些重要的关于切入点的概念。
一些概念
Spring.NET的切入点和通知是相互独立的,因此针对不同的通知类型可以使用相同的切入点。
Spring.Aop.IPointcut 接口是最核心的,是用来将通知定位到特定的类型或者方法,接口细节如下:
public interface IPointcut
{
ITypeFilter TypeFilter { get; }
IMethodMatcher MethodMatcher { get; }
}
将IPointcut 接口拆分成两个部分可以复用类型、方法匹配的功能和一些细粒度的操作(例如和其他方法匹配器(method matcher)的“union”操作)。
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代理生成的时候进行,而不是在每次方法调用的时候都进行一次。如果一个特定的方法在两个参数的匹配方法中匹配成功,并且IMethodMatcher 的IsRuntime 属性返回true,那么那个三个参数的方法就会在每一次 方法调用的时候被调用。这样,切入点就能在每次目标通知执行之前查看传入方法的参数。
大多IMethodMatchers 都是静态的,意味着他们的IsRuntime属性总是返回false。在这种情况下,三个参数的方法就不会被调用。所以如果有可能的话,尽量使用静态的切入点,因为AOP框架会在AOP代理产生的时候缓存这些切入点的判断结果。
关于切入点的一些操作
Spring.NET支持切入点的一些操作有:例如,union和intersection
union意味着方法中至少有一个符合切入点。
intersection意味着方法所有的切入点都符合。
union通常更有用。
切入点可以通过Spring.Aop.Support.Pointcuts 类中的静态方法结合,也可以使用在同一命名空间下的ComposablePointcut 类结合。
一些切入点的便捷应用
Spring.NET提供了一些便捷的切入点使用方式。一些可以直接使用,其他的可以作为各个应用特定的切入点的子类来应用。
静态切入点
静态切入点是以方法和目标类为基础,不考虑方法的传入参数。静态切入点足够应付,并且是最适合,大多的使用场景。这样,Spring.NET只要在一个方法第一次调用的时候判断一次切入点,在这个之后就不需要再每次调用的时候都进行判断了。
让我们考虑一些静态切入点在Spring.NET 中的使用场景:
使用正则表达式
一个常见的描述静态切入点使用的是正则表达式。包括Spring.NET,大部分的AOP框架都已经实现这个功能。Spring.Aop.Support.SdkRegularExpressionMethodPointcut是一个泛型的正则切入点,使用了.NET BCL中的正则类。
使用这个类,你可以先提供一系列的模式字符串(pattern Strings)。只要一个规则满足,这个切入点就会被判断为true(所以结果是这些切入点的union的操作结果)。匹配通过类的全名来判断,因此你可以使用这个切入点在任意的命名空间下的任何类中应用通知。
以下是一个使用场景:
<object id="settersAndAbsquatulatePointcut"
type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</object>
为了方便,Spring为我们提供了RegularExpressionMethodPointcutAdvisor类来引用一个IAdvice接口实例,同时定义切入点规则(要记住IAdvice实例可以是一个拦截器,前置通知,异常通知等等)。这种简化的写法,把切入点和通知器写在同一个object标签里面,例如这样:
<object id="settersAndAbsquatulateAdvisor"
type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop">
<property name="advice">
<ref local="objectNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</object>
RegularExpressionMethodPointcutAdvisor类可以作为任何的通知类型。如果你只有一个规则你可以使用这个属性名字规则然后为其特定一个值而不是定义所有的属性规则然后配上一个值列表。
你也可能从System.Text.RegularExpressions 命名空间下指定一个正则对象。内置的RegexConverter类将会提供解析。可以看6.4节, “Built-in TypeConverters”以找到更多的Spring内置类型转换器。正则对象在IoC容器中被创建成其他的任意对象。通过使用一个内部对象定义是一个很方便的方法来使定义和PointcutAdvisor声明更加接近。需要注意的是,如果在构造器中没有任何显式的指定的话,SdkRegularExpressionMethodPointcut类有一个默认配置属性来设置正则表达式的配置。
使用特性标签
切入点可以通过方法上面的特性(attribute)来指定。切入点关联的通知接下来就会通过解析特性标签来配置。AttributeMatchMethodPointCut类提供这种功能。以下例子中的切入点可以匹配所有的带有Spring.Attributes.CacheAttribute特性的标签方法:
<object id="cachePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop">
<property name="Attribute" value="Spring.Attributes.CacheAttribute, Spring.Core"/>
</object>
就像下面展示的一样,这种方式也可以和DefaultPointcutAdvisor一起使用
<object id="cacheAspect" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
<property name="Pointcut">
<object type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop">
<property name="Attribute" value="Spring.Attributes.CacheAttribute, Spring.Core"/>
</object>
</property>
<property name="Advice" ref="aspNetCacheAdvice"/>
</object>
这里的aspNetCacheAdvice 是一个IMethodInterceptor 接口的实现,它缓存了方法的返回值。可以查阅SDK文档Spring.Aop.Advice.CacheAdvice 来获得更多与这个通知相关的信息。
为了方便,AttributeMatchMethodPointcutAdvisor 类定义另一种基于特性,更加简练的泛型DefaultPointcutAdvisor类通知器。以下是一个例子:
<object id="AspNetCacheAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop">
<property name="advice">
<object type="Aspect.AspNetCacheAdvice, Aspect"/>
</property>
<property name="attribute" value="Framework.AspNetCacheAttribute, Framework" />
</object>
动态切入点
动态切入点要比静态切入点更加耗费性能。他们要考虑方法的传入参数和静态的信息。这就意味着他们必须判断每一个方法的调用,这种判断结果是不能被缓存的,因为传入的参数多种多样。
一个常见的例子就是控制流切入点(control flow pointcut)。
控制流切入点
Spring.NET控制流切入点在概念上类似于AspectJ 的cflow切入点,尽管没有它那么强大。(当前无法指定一个切入点在其他切入点下执行)。一个控制流切入点肯定是动态的,这因为它要根据现在的每个方法调用时候的调用堆栈来判断。例如,一个类型A的方法A() 调用了类型B的方法B(),然后类型B的方法B()就在类型A的方法A()的控制流中执行。仅当类型B的方法B()被调用的时候,控制流切入点就能应用在类型A的方法A() ,而不是类型A的方法A() 在其他调用堆栈中执行。控制流切入点在Spring.Aop.Support.ControlFlowPointcut 类中详细定义。
当使用控制流切入点的时候,需要注意一些问题。在运行时,JIT编译器会内联一些方法,主要是为了提升性能,但是这会导致这个方法会在调用堆栈中消失。这是因为内联操作把被调用者的IL代码插入到调用者的IL代码中来有效地移除方法调用。这些信息可以从System.Diagnostics.StackTrace中获得,这样的话使用ControlFlowPointcut就会受到这些优化的影响而不匹配,这是因为这些方法被内联了。
总的来说,一个足够小的方法,可能只有几行代码(IL代码小于32 bytes)容易被内联。对于这个感兴趣的可以读David Notario的博客(JIT Optimizations I and JIT Optimizations II)。并且,当一个程序集按照发布模式的配置被编译的时候,元数据会告知CLR使用JIT优化。当按照调试模式的配置的时候,CLR会禁用(可能一些)JIT优化。根据以往经验来说,在调试模式下JIT是会关闭内联的。
一个保证你的控制流切入点不会被忽略的方法是使用System.Runtime.CompilerServices.MethodImplAttribute特性,然后将其赋值为MethodImplOptions.NoInlining。在这个简单的例子中,如果代码在发行模式中编译就不会匹配到“GetAge”方法。
public int GetAge(IPerson person)
{
return person.GetAge();
}
而且,使用上面的特性方法会在发行编译中不会进行内联。
[MethodImpl(MethodImplOptions.NoInlining)]
public int GetAge(IPerson person)
{
return person.GetAge();
}
自定义切入点
由于Spring.NET 中的切入点都是.NET 的基础类型,而不是基于语言的特征(language features )(例如在AspectJ中),因此无论对于静态切入点还是动态切入点,都可以声明自定义切入点。然而在AspectJ语法中, 现在却没有现成、成熟的自定义切入点的声明方式。在Spring.NET 中,自定义切入点就像一般实体模型一样可以被任意地关联调用。
Spring.NET 提供了有效的切入点的超类来支持你自定义切入点的实现。
因为静态切入点是最常见并且最有用的切入点类型,你只要继承StaticMethodMatcherPointcut,就像下面展示的那样,你只要实现一个抽象方法就行(尽管也可以重写其他方法来自定义行为):
public class TestStaticPointcut : StaticMethodMatcherPointcut {
public override bool Matches(MethodInfo method, Type targetType) {
// return true if custom criteria match
}
}
关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-切入点(pointcut)API的更多相关文章
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-简介
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 简介 Aspect-Orie ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-通知(Advice)API
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 让我们看看 Spring.N ...
- 面向切面编程 ( Aspect Oriented Programming with Spring )
Aspect Oriented Programming with Spring 1. 简介 AOP是与OOP不同的一种程序结构.在OOP编程中,模块的单位是class(类):然而,在AOP编程中模块的 ...
- 关于面向切面编程Aspect Oriented Programming(AOP)
最近学到spring ,出来了一个新概念,面向切面编程,下面做个笔记,引自百度百科. Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题.AOP主要实 ...
- javascript 高阶函数 实现 AOP 面向切面编程 Aspect Oriented Programming
AOP的主要作用是吧一些跟核心业务逻辑模块无关的功能 -日志统计, 安全控制, 异常处理- 抽离出来, 再通过"动态织入"的方式掺入业务逻辑模块中. 这里通过扩展Function. ...
- 程序员笔记|Spring IoC、面向切面编程、事务管理等Spring基本概念详解
一.Spring IoC 1.1 重要概念 1)控制反转(Inversion of control) 控制反转是一种通过描述(在java中通过xml或者注解)并通过第三方去产生或获取特定对象的方式. ...
- Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)
在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...
- Spring AOP:面向切面编程,AspectJ,是基于spring 的xml文件的方法
导包等不在赘述: 建立一个接口:ArithmeticCalculator,没有实例化的方法: package com.atguigu.spring.aop.impl.panpan; public in ...
随机推荐
- ctags+cscope替换sourceinsight
背景 windows环境开发+linux交叉编译的开发模式,代码阅读和编写都用的source-insight. 除了检索,跳转,工程构建等方面,sourceinsight自带了一些宏语言,可以轻松实现 ...
- bayes学习笔记
贝叶斯(BAYES)判别思想是根据先验概率求出后验概率,并依据后验概率分布作出统计推断.所谓先验概率,就是用概率来描述人们事先对所研究的对象的认识的程度:所谓后验概率,就是根据具体资料.先验概率.特定 ...
- Vue打包app
前言 公司之前用的app就是一个套壳挂个链接就能用的app,后来需要添加微信分享方便传播,没办法只好做成混合式的app了, 因为之前做.net用vs可以创建cordova项目也试着玩过,就决定用cor ...
- COMMIT和ROLLBACK的用法
从功能上划分,SQL语言可以分为DDL,DML和DCL三大类. 1.DDL(Data Definition Language) 数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言 : C ...
- hdu 1172 猜数字
猜数字 Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- [bzoj1033] [ZJOI2008]杀蚂蚁antbuster
Description 最近,佳佳迷上了一款好玩的小游戏:antbuster.游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试图把蛋糕搬回蚂蚁窝.而你的任 ...
- [YNOI2017][bzoj4811][luogu3613] 由乃的OJ/睡觉困难综合症 [压位+树链剖分+线段树]
题面 BZOJ题面,比较不清晰 Luogu题面,写的比较清楚 思路 原题目 我们先看这道题的原题目NOI2014起床困难综合症 的确就是上树的带修改版本 那么我们先来解决这个原版的序列上单次询问 二进 ...
- BZOJ1855 [Scoi2010]股票交易 【单调队列优化dp】
题目链接 BZOJ1855 题解 设\(f[i][j]\)表示第\(i\)天结束时拥有\(j\)张股票时的最大收益 若\(i \le W\),显然在这之前不可能有交易 \[f[i][j] = max\ ...
- 蓝牙HC-05与HC-06对比指令集
高电平->AT命令响应工作状态 低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06虽然可以做主机也可以做从机,但是不能切 ...
- Topcoder SRM 603 div1题解
昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点 ...