关于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 ...
随机推荐
- 第一次玩博客 感觉自己特别low
第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动第一天来 来好激动 ...
- linux socket c/s上传文件
这是上传文件的一个示例,可以参照自行修改成下载或者其它功能. 在上传时,需要先将文件名传到服务器端,这是采用一个结构体,包含文件名及文件名长度(可以用于校验),防止文件名乱码. client #inc ...
- 服务器tomcat配置教程
2018年上学期期末课程设计做了一个留言板,但是我需要把这个Jave Web弄到我的服务器上 首先我们可以安装jdk tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与 ...
- HDU 4109 Instrction Arrangement(DAG上的最长路)
把点编号改成1-N,加一点0,从0点到之前任意入度为0的点之间连一条边权为0的边,求0点到所有点的最长路. SPFA模板留底用 #include <cstdio> #include < ...
- UVa 11374 - Airport Express ( dijkstra预处理 )
起点和终点各做一次单源最短路, d1[i], d2[i]分别代表起点到i点的最短路和终点到i点的最短路,枚举商业线车票cost(a, b); ans = min( d1[a] + cost(a, b ...
- poj 1035 纯正的字符串水
Spell checker Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 22673 Accepted: 8258 De ...
- CPU封装技术介绍
所谓“CPU封装技术”是一种将集成电路用绝缘的塑料或陶瓷材料打包的技术.以CPU为例,我们实际看到的体积和外观并不是真正的CPU内核的大小和面貌,而是CPU内核等元件经过封装后的产品. CPU封装对于 ...
- Lettcode Kth Largest Element in an Array
Lettcode Kth Largest Element in an Array 题意:在无序数组中,寻找第k大的数字,注意这里考虑是重复的. 一直只会简单的O(nlogn)的做法,听说这题有O(n) ...
- 洛谷 P2041 分裂游戏 解题报告
P2041 分裂游戏 题目描述 有一个无限大的棋盘,棋盘左下角有一个大小为 n 的阶梯形区域,其中最左下角的那个格子里有一枚棋子.你每次可以把一枚棋子"分裂"成两枚棋子,分别放在原 ...
- macOS Sierra下如何打开任何来源(10.12系统)
转载声明:本站文章无特别说明皆为原创,转载请注明:史蒂芬周的博客, 一定有很多朋友和小子一样,迫不及待的升级到了macOS Sierra,随之而来的是第三方应用都无法打开了,提示无法打开或者扔进废纸篓 ...