AOP:
面向切面编程,最重要的就是这个切面的定义。切面中包括通知和切点。通知定义的是具体的行为,具体要做什么,比如日志、权限检查等,有前置通知,后置通知等。行为在面向对象编程中,即指方法。那么切面自然对应为一个类。
切入点就是这些方法所要执行的位置。在AOP中除了在方法执行的时候,还支持比如类加载过程中,进行通知。但在SpringAOP中,只支持在方法的位置进行通知。可以进行通知的位置都称之为连接点。切点是基于业务等原因归类一些连接点的集合。连接点是可以通知的地方,而切点是具体要通知哪些地方。
此时还需要把通知和切入点结合起来,即使用哪个通知,以及在哪个切点使用,这就是通知器的作用。既然有了切面了,为何还要有这个通知器呢?简单的区别就是,一个切面包括可以多个切点和多个通知,而通知器只会包含一个切点和一个通知。在具体的编码中,使用注解时,将通知和切点自然的放在一块,我们可能会忽略掉这个通知器。
上述三个概念是AOP中最为基本的三个概念。下面我们看一点源码:
Pointcut是一个接口,有很多的实现类,他的作用就是决定某一个方法是否需要被切面增强。有一个接口方法
MethodMatcher getMethodMatcher();
但是具体的判断逻辑,他是交给MethodMatcher这个接口来完成。
在这个接口中我们就看到了matches这个方法。
Pointcut有很多实现类,比如JdkRegexpMethodPointcut, 从这个类的名字我们大概了解一点他的作用,通过正则表达来判断这个方法是否需要增强。想说的一点是,由于具体方法判断由MethodMatcher来完成,所以他的很多实现类同时实现了这个MethodMatcher接口。
JdkRegexpMethodPointcut这个类就是实现了MethodMatcher接口,matches的实现如下:
protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.matches();
}
再看一个使用简单逻辑判断的类NameMatchMethodPointcut,就是根据名字来判断是否对方法进行增强。
@Override
public boolean matches(Method method, Class<?> targetClass) { for (String mappedName : this.mappedNames) { if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) { return true; } } return false;
}
接下来我们看下通知器的源码:
以DefaultPointcutAdvisor这个类为例。这个类中有其实有两个属性:Pointcut 和Advice。一一解释:
定义了一个默认的Pointcut:
private Pointcut pointcut = Pointcut.TRUE;
这个Pointcut.true是一个单例,并且是Pointcut的一个子类TruePointcut,他返回一个TrueMethodMatcher,也是一个单例,同时也是MethodMatcher的一个子类,他的matches返回true。最终的意思就是他默认所有的方法都需要增强。
这个Advice的声明是在他的父类AbstractGenericPointcutAdvisor中,定义为了private,但是提供setter和getter方法。
(关于Spring AOP原理,第一部分写到这儿,后面会继续一直写完)