Spring技术内幕:Spring AOP的实现原理(一)

一、SpringAOP的概述 1、AOP概念 AOP是Aspect-Oriented Programming(面向切面编程)的简称。维基百科的解释如下: Aspect是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern)。从关注点中分离出横切关注点是面向切面的程序设计的核心。分离关注点使解决特定领域问题的代码从业务逻辑代码中独立出来,业务逻辑的代码中不再含有针对特定领用问题代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好的管理起来。 2、Advice通知 Advice定义在连接点为切面增强提供织入接口。在Spring AOP中,他主要描述Spring AOP围绕方法调用而注入的切面行为。Advice是定义在org.aopalliance.aop.Advice中的接口。在Spring AOP使用这个统一接口,并通过这个接口为AOP切面增强的织入功能做了更多的细节和扩展,比如提供了更具体的通知类型,如BeforeAdvice,AfterAdvice,ThrowsAdvice等。 2.1 BeforeAdvice 首先我们从BeforeAdvice开始: 在BeforeAdvice的继承关系中,定义了为待增强的目标方法设置的前置增强接口MethodBeforeAdvice,使用这个前置接口需要实现一个回调函数:

void before() throws Throwable;

作为回调函数,before方法的实现在Advice中被配置到目标方法后,会在调用目标方法时被回调。具体的参数有:Method对象,这个参数是目标方法的反射对象;Object[]对象数组,这个对象数组中包含目标方法的输入参数。以CountingBeforeAdvice为例来说明BeforeAdvice的具体使用,CountBeforeAdvice是接口MethodBeforeAdvice的具体实现,他只是统计被调用方法的次数,作为切面增强实现,他会根据调用方法的方法名进行统计,把统计结果根据方法名和调用次数作为键值对放入一个map中。代码如下:

{(Method m, Object[] args, Object target) throws Throwable {//以目标对象方法作为参数,调用父类MethodCounter的count方法统计方法调用次数count(m);}}CountingBeforeAdvice的父类MethodCounter的源码如下:{//方法名—>方法调用次数的map集合,存储方法的调用次数private HashMap<String, Integer> map = new HashMap<String, Integer>();allCount;(Method m) {count(m.getName());}(String methodName) {//从方法名—>方法调用次数集合中获取指定名称方法的调用次数Integer i = map.get(methodName);//如果调用次数不为null,则将调用次数加1,如果调用次数为null,则设置调用次数为1i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);//重新设置集合中保存的方法调用次数map.put(methodName, i);//所有方法总调用次数加1++allCount;}(String methodName) {Integer i = map.get(methodName);return (i != null ? i.intValue() : 0);}() {return allCount;}(Object other) {return (other != null && other.getClass() == this.getClass());}() {return getClass().hashCode();}}

2.2 AfterAdvice 在Advice的实现体系中,Spring还提供了AfterAdvice这种通知类型,这里以AfterReturningAdvice通知的实现为例,代码如下:

{afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;}

afterReturning方法也是一个回调函数,AOP应用需要在这个接口实现中提供切面增强的具体设计,在这个Advice通知被正确配置以后,在目标方法调用结束并成功返回的时候,,接口会被SpringAOP调用。与前面分析的一样,在Spring AOP包中,同样可以看到CountingAfterReturningAdvice,实现基本一致:

{(Object o, Method m, Object[] args, Object target) throws Throwable {//调用父类MethodCounter的count方法,统计方法的调用次数count(m);}}

在实现AfterReturningAdvice的接口方法afterReturning中,可以调用MethodCounter的count方法,从而完成根据方法名对目标方法调用次数的统计。 2.3 ThrowsAdvice 下面我们来看一下Advice通知的另一种类型ThrowsAdvice。对于ThrowsAdvice,并没有制定需要实现的接口方法,他在抛出异常时被回调,这个回调是AOP使用反射机制来完成的。可以通过CountingThrowsAdvice来了解ThrowsAdvice的使用方法:

{(IOException ex) throws Throwable {count(IOException.class.getName());}(UncheckedException ex) throws Throwable {count(UncheckedException.class.getName());}}

3、Pointcut切点 决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强的方法的集合,这些集合的选取可以按照一定的规则来完成。Pointcut通常意味着标识方法,例如,这些需要增强的地方可以由某个正则表达式进行标识,或根据某个方法名进行匹配。源码如下:

public interface Pointcut {//获取类过滤器ClassFilter getClassFilter();//获取匹配切入点的方法 MethodMatcher getMethodMatcher();//总匹配的标准切入点实例Pointcut TRUE = TruePointcut.INSTANCE;}

查看Pointcut切入点的继承体系,发现Pointcut切入点的实现类非常的多,如针对注解配置的AnnotationMatchingPointcut、针对正则表达式的JdkRegexpMethodPointcut等等,我们以JdkRegexpMethodPointcut为例,分析切入点匹配的具体实现,源码如下:

{//要编译的正则表达式模式private Pattern[] compiledPatterns = new Pattern[0];//编译时要排除的正则表达式模式private Pattern[] compiledExclusionPatterns = new Pattern[0];(String[] patterns) throws PatternSyntaxException {this.compiledPatterns = compilePatterns(patterns);}(String[] excludedPatterns) throws PatternSyntaxException {this.compiledExclusionPatterns = compilePatterns(excludedPatterns);}(String pattern, int patternIndex) {Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);return matcher.matches();}(String candidate, int patternIndex) {Matcher matcher = this.compiledExclusionPatterns[patternIndex].matcher(candidate);return matcher.matches();}//将给定的字符串数组编译为正则表达的模式private Pattern[] compilePatterns(String[] source) throws PatternSyntaxException {Pattern[] destination = new Pattern[source.length];for (int i = 0; i < source.length; i++) {destination[i] = Pattern.compile(source[i]);}return destination;}}放下一处烦恼,收获一个惊喜;放下一种偏见,收获一种幸福;

Spring技术内幕:Spring AOP的实现原理(一)

相关文章:

你感兴趣的文章:

标签云: