系列文章目录
切点匹配解析
Advisor与@Aspect解析
Advisor获取解析
文章目录
前言
springAOP获取切面对象这个过程中获取了切点对象pointcut,在Advisor获取解析中的getAdvisor()方法中通过调用getPointcut()方法得到切点对象
getPointcut()过程解析
参数:
Method candidateAdviceMethod: 目前匹配的方法对象(@aspect修饰类中的方法)
Class<?> candidateAspectClass:目前匹配的类对象(@aspect修饰的类)
返回值类型
AspectJExpressionPointcut
可以看见AspectJExpressionPointcut类实现了Pointcut接口的同时也实现了ClassFilter与MethodMatcher接口(后续切点值匹配时起作用)
getPointcut()主要过程:
1.解析当前方法注解信息并获取切点表达式值
2.实例化切点对象并设置切点表达式
// 获得切点实例
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass){
// 解析切点类信息与切点表达式信息 封装在AspectJAnnotation对象中
AspectJAnnotation<?> aspectJAnnotation = findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null)
return null;
// 实例化切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
pointcut.setExpression(aspectJAnnotation.getPointcutExpression());
return pointcut;
}
可以看见获取切点所需要的主要信息是从findAspectJAnnotationOnMethod()方法中获得
findAspectJAnnotationOnMethod()
findAspectJAnnotationOnMethod()是SimulateAbstractAspectJAdvisorFactory类的成员方法(模拟AbstractAspectJAdvisorFactor类)
可以发现findAspectJAnnotationOnMethod()方法中出现:
AspectJAnnotation类以及ASPECTJ_ANNOTATION_CLASSES常量
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class[]{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
ASPECTJ_ANNOTATION_CLASSES常量SimulateAbstractAspectJAdvisorFactory类所定义的常量类数组其值为各个修饰切点的注解类
在了解ASPECTJ_ANNOTATION_CLASSES信息后就可以清楚知道findAspectJAnnotationOnMethod()方法的功能:
遍历注解类数组通过findAnnotation()找到当前方法所对应的注解类,并将返回值封装为AspectJAnnotation<?>类型
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class[] var1 = ASPECTJ_ANNOTATION_CLASSES;
int var2 = var1.length;
for (int var3 = 0; var3 < var2; ++var3) {
Class<?> clazz = var1[var3];
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
若想明白AspectJAnnotation<?>类型究竟是什么还需要去探究findAnnotation()方法
findAnnotation()
<A extends Annotation> AspectJAnnotation<A>
泛型A需要实现Annotation接口
AnnotationUtils.findAnnotation(method, toLookFor)
匹配当前方法与当前注释 若成功则返回A类(该类实现Annotation接口 如Before.class...)
若匹配成功将AnnotationUtils.findAnnotation()的返回结果封装为AspectJAnnotation类的对象
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
return result != null ? new AspectJAnnotation(result) : null;
}
AspectJAnnotation类
AspectJAnnotation类是在SimulateAbstractAspectJAdvisorFactory类中实现的静态内部类,,同时它还是一个泛型类;该类封装A annotation对象(实现Annotation接口即可)
通过其构造方法可以得知其主要功能:
1.封装获得的annotation对象(泛型)
2.通过determineAnnotationType方法获得其annotation类型
3.通过resolveExpression方法获得切点表达式
4.获取注解参数
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_ATTRIBUTES = new String[]{"pointcut", "value"};
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap(8);
private final A annotation;
private final AspectJAnnotationType annotationType;
private final String pointcutExpression;
private final String argumentNames;
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = this.determineAnnotationType(annotation);
// 解析切点表达式
try {
this.pointcutExpression = this.resolveExpression(annotation);
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = argNames instanceof String ? (String) argNames : "";
} catch (Exception var3) {
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", var3);
}
}
}
determineAnnotationType()
AspectJAnnotation类内部定义一个HashMap存储注解类与对应的枚举类AspectJAnnotationType
determineAnnotationType 方法则是根据传入的注解annotation获取其在HashMap中的对应value值并返回
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap(8);
//HashMap赋值
static {
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
}
// 定义静态枚举类
protected static enum AspectJAnnotationType {
AtPointcut,
AtAround,
AtBefore,
AtAfter,
AtAfterReturning,
AtAfterThrowing;
private AspectJAnnotationType() {
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
AspectJAnnotationType type = (AspectJAnnotationType) annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
} else {
throw new IllegalStateException("Unknown annotation type: " + annotation);
}
}
resolveExpression()
EXPRESSION_ATTRIBUTES 是AspectJAnnotation类定义的常量字符数组封装pointcut与value两个字符串,主要用于区别当前注解类是pointcut类型还是常规类型(@Before、@after…)
resolveExpression的主要过程:
通过AnnotationUtils.getValue找到当前annotation所对应的值并返回
private static final String[] EXPRESSION_ATTRIBUTES = new String[]{"pointcut", "value"};
private String resolveExpression(A annotation) {
String[] var2 = EXPRESSION_ATTRIBUTES;
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String attributeName = var2[var4];
// 获取对应注解对象的pointcut值或value值(execution(* foo()))
Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String) {
String str = (String)val;
if (!str.isEmpty()) {
return str;
}
}
}
throw new IllegalStateException("Failed to resolve expression: " + annotation);
}
总结
getPointcut()主要功能:
1.获取当前方法对应的注释信息并将其封装为AspectJAnnotation对象
2.实例化切点后利用封装好的信息对切点中信息进行赋值