Spring源码深度解析(郝佳)-学习-源码解析-aop切面表达式匹配(四)

经过aop切面表达式解析(一)aop切面表达式解析(二)分析,我们己经知道表达式解析成相应和 PatternPointcut,就如下例中,切面表达式execution(* com.spring_101_200.test_111_120.test_117_excution.excution1..(…))是如何匹配到MyService类中的service方法的呢?带着疑问,我们今天来继续跟进源码。

AspectJTest

@Aspect
@Configuration
public class AspectJTest {
    @Before("execution(* com.spring_101_200.test_111_120.test_117_excution.excution1.*.*(..))")
    public void beforeTest() {
        System.out.println("beforeTest");
    }
}

今天我们主要分析Spring 是如何解析 execution(* com.spring_101_200.test_111_120.test_117_excution.excution1..(…)) 表达式。

MyService.java

@Service
public class MyService {
    public void service() {
        System.out.println("serivce");
    }
}

spring_117_excution1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <context:component-scan base-package="com.spring_101_200.test_111_120.test_117_excution.excution1"></context:component-scan>


</beans>

测试:

public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_101_200/config_111_120/spring117_excution/spring_117_excution1.xml");
    MyService myService = ac.getBean(MyService.class);
    myService.service();
}

结果输出:

在这里插入图片描述

经过上面的示例,现在,我们来进行源码分析。

AopUtil.java

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}
	//获取切面表达式的方法匹配
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}
	//获取当前类及祖先类所有接口
	Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	classes.add(targetClass);
	for (Class<?> clazz : classes) {
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			if ((introductionAwareMethodMatcher != null &&
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}
	return false;
}

只要目标类中任意方法被匹配,将返回 true,表示该类是可以设置为代理的。

AspectJExpressionPointcut.java

public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
	//检测切面表达式是否解析完成
	checkReadyToMatch();
	//因为存在继承,实现接口,所以,目标类调用的方法不一定是自己的类方法,可能是继承而得来的。
	//因此,这里,获取方法的实际所在类的方法,比如 A 类继承 B类,调用 B 类的 b 方法,
	//目标方法即 :B.b()方法,而不是 A.b()方法
	Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
	//获取影子匹配
	ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
	//只要返回 true ,则表示该类可创建代理
	if (shadowMatch.alwaysMatches()) {
		return true;
	}
	else if (shadowMatch.neverMatches()) {
		return false;
	}
	else {
		if (beanHasIntroductions) {
			return true;
		}
		RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
		return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
	}
}

AspectJExpressionPointcut.java

private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
	//从缓存中获取
	ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
	if (shadowMatch == null) {
		synchronized (this.shadowMatchCache) {
			//如果缓存中不存在,再次确认一遍
			PointcutExpression fallbackExpression = null;
			Method methodToMatch = targetMethod;
			shadowMatch = this.shadowMatchCache.get(targetMethod);
			if (shadowMatch == null) {
				try {
					//开始匹配方法表达式
					shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
				}
				catch (ReflectionWorldException ex) {
					try {
						fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
						if (fallbackExpression != null) {
							shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
						}
					}
					catch (ReflectionWorldException ex2) {
						fallbackExpression = null;
					}
				}
				if (shadowMatch == null && targetMethod != originalMethod) {
					methodToMatch = originalMethod;
					try {
						shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
					}
					catch (ReflectionWorldException ex3) {
						try {
							fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
							if (fallbackExpression != null) {
								shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
							}
						}
						catch (ReflectionWorldException ex4) {
							fallbackExpression = null;
						}
					}
				}
				if (shadowMatch == null) {
					shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
				}
				else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
					shadowMatch = new DefensiveShadowMatch(shadowMatch,
							fallbackExpression.matchesMethodExecution(methodToMatch));
				}
				this.shadowMatchCache.put(targetMethod, shadowMatch);
			}
		}
	}
	return shadowMatch;
}

PointcutExpressionImpl.java

public ShadowMatch matchesMethodExecution(Method aMethod) {
	ShadowMatch match = matchesExecution(aMethod);
	if (MATCH_INFO && match.maybeMatches()) {
		System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
				+ (match.alwaysMatches() ? "YES" : "MAYBE"));
	}
	return match;
}

PointcutExpressionImpl.java

private ShadowMatch matchesExecution(Member aMember) {
	Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);
	ShadowMatchImpl sm = getShadowMatch(s);
	sm.setSubject(aMember);
	sm.setWithinCode(null);
	sm.setWithinType(aMember.getDeclaringClass());
	return sm;
}

ReflectionShadow.java

public static Shadow makeExecutionShadow(World inWorld, java.lang.reflect.Member forMethod, MatchingContext withContext) {
	Kind kind = (forMethod instanceof Method) ? Shadow.MethodExecution : Shadow.ConstructorExecution;
	Member signature = ReflectionBasedReferenceTypeDelegateFactory.createResolvedMember(forMethod, inWorld);
	ResolvedType enclosingType = signature.getDeclaringType().resolve(inWorld);
	return new ReflectionShadow(inWorld, kind, signature, null, enclosingType, null, withContext);
}

ReflectionBasedReferenceTypeDelegateFactory.java

public static ResolvedMember createResolvedMember(Member reflectMember, World inWorld) {
	if (reflectMember instanceof Method) {
		return createResolvedMethod((Method) reflectMember, inWorld);
	} else if (reflectMember instanceof Constructor) {
		return createResolvedConstructor((Constructor) reflectMember, inWorld);
	} else {
		return createResolvedField((Field) reflectMember, inWorld);
	}
}
public static ResolvedMember createResolvedMethod(Method aMethod, World inWorld) {
	ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD,
			toResolvedType(aMethod.getDeclaringClass(), (IReflectionWorld) inWorld), aMethod.getModifiers(), toResolvedType(
					aMethod.getReturnType(), (IReflectionWorld) inWorld), aMethod.getName(), toResolvedTypeArray(
					aMethod.getParameterTypes(), inWorld), toResolvedTypeArray(aMethod.getExceptionTypes(), inWorld), aMethod);
	if (inWorld instanceof IReflectionWorld) {
		ret.setAnnotationFinder(((IReflectionWorld) inWorld).getAnnotationFinder());
	}
	//创建Java15GenericSignatureInformationProvider对象
	ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
	return ret;
}

PointcutExpressionImpl.java

private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
	//对表达式进行匹配
	org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
	Test residueTest = Literal.TRUE;
	ExposedState state = getExposedState();
	//如果返回的值是模棱两可的,进一步确认
	if (match.maybeTrue()) {
		//在写第六篇博客时,发现这一行代码很重要,因此回头来补这行代码解析
		residueTest = pointcut.findResidue(forShadow, state);
	}
	ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);
	sm.setMatchingContext(this.matchContext);
	return sm;
}

Pointcut.java

public final FuzzyBoolean match(Shadow shadow) {
	//每个Shadow对象的 shadowId 不一样,每 new 一个,shadowId + 1,如果当前 shadow 是最后一个了,直接返回
	if (shadow.shadowId == lastMatchedShadowId) {
		return lastMatchedShadowResult;
	}
	FuzzyBoolean ret;
	if (shadow.getKind().isSet(couldMatchKinds())) {
		//开始匹配
		ret = matchInternal(shadow);
	} else {
		ret = FuzzyBoolean.NO;
	}
	lastMatchedShadowId = shadow.shadowId;
	lastMatchedShadowResult = ret;
	return ret;
}

KindedPointcut.java

protected FuzzyBoolean matchInternal(Shadow shadow) {
	//目标方法类型和切面表达式的方法类型是否匹配
	if (shadow.getKind() != kind) {
		return FuzzyBoolean.NO;
	}
	//@Before("lock(* *(java.util.Map<com..Model, com..Model>, ..))")
	//如果切面表达式的 kind 是 lock,方法的类型也是 lock,直接返回 YES
	if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) {
		return FuzzyBoolean.YES;
	}
	//@Before("unlock(* *(java.util.Map<com..Model, com..Model>, ..))")
	//如果切面表达式配置了 unlock,并且方法的类型也是 unlock,直接返回 YES
	if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) {
		return FuzzyBoolean.YES;
	}
	//切面表达式和方法匹配
	if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) {
		if (kind == Shadow.MethodCall) {
			//如果上面进行匹配返回false,并且方法类型是 method-call
			warnOnConfusingSig(shadow);
		}
		return FuzzyBoolean.NO;
	}
	return FuzzyBoolean.YES;
}

SignaturePattern.java

public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {
	//如果目标方法签名为空,直接返回 false 
	if (joinPointSignature == null) {
		return false;
	}
	//如果目标方法的类型和切面表达式配置的类型不相等,返回 false 
	if (kind != joinPointSignature.getKind()) {
		return false;
	}
	//如果切面表达式是ADVICE类型,直接返回 true 
	if (kind == Member.ADVICE) {
		return true;
	}

	boolean subjectMatch = true;
	//是否需要进行方法上注解匹配
	boolean wantsAnnotationMatch = wantToMatchAnnotationPattern();
	JoinPointSignatureIterator candidateMatches = joinPointSignature.getJoinPointSignatures(world);
	while (candidateMatches.hasNext()) {
		JoinPointSignature aSig = candidateMatches.next();
		//精确匹配
		FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch);
		if (matchResult.alwaysTrue()) {
			return true;
		} else if (matchResult.alwaysFalse()) {
			return false;
		}
		//如果返回的是 MAYBE,则需要去看该方法的修饰符,注解,和 throws 异常
		subjectMatch = false;
		if (wantsAnnotationMatch) {
			return false;
		}
	}
	return false;
}
private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods, boolean subjectMatch) {
	//如果方法是桥接方法,返回 MAYBE
	if (aMember.isBridgeMethod() && !allowBridgeMethods) {
		return FuzzyBoolean.MAYBE;
	}

	//如果方法的修饰符不匹配,返回 NO
	if (subjectMatch && !modifiers.matches(aMember.getModifiers())) {
		return FuzzyBoolean.NO;
	}

	FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;
	if (kind == Member.STATIC_INITIALIZATION) {
		//如果类型是静态初始化类型
		matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);
	} else if (kind == Member.FIELD) {
		//如果类型是属性
		matchesIgnoringAnnotations = matchesExactlyField(aMember, inAWorld);
	} else if (kind == Member.METHOD) {
		//如果类型是方法
		matchesIgnoringAnnotations = matchesExactlyMethod(aMember, inAWorld, subjectMatch);
	} else if (kind == Member.CONSTRUCTOR) {
		//如果类型是构造方法
		matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);
	}
	if (matchesIgnoringAnnotations.alwaysFalse()) {
		return FuzzyBoolean.NO;
	}

	//进行方法注解匹配
	if (subjectMatch) {
		// The annotations must match if specified
		if (!matchesAnnotations(aMember, inAWorld).alwaysTrue()) {
			return FuzzyBoolean.NO;
		} else {
			return matchesIgnoringAnnotations;
		}
	} else {
		//如果注解类型是任意类型
		if (annotationPattern instanceof AnyAnnotationTypePattern) {
			return matchesIgnoringAnnotations;
		} else {
			return FuzzyBoolean.NO;
		}
	}
}

private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {
	//如果方法参数不匹配,返回 NO
	if (parametersCannotMatch(aMethod)) {
		return FuzzyBoolean.NO;
	}
	//如果方法的名称不匹配,返回 NO
	if (!name.matches(aMethod.getName())) {
		return FuzzyBoolean.NO;
	}
	//如果切面表达式配置的方法抛出异常不匹配,返回 NO
	if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {
		return FuzzyBoolean.NO;
	}

	//如果包名和类名匹配不是*,则对第一项进行匹配
	if (!declaringType.isStar()) {
		if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {
			return FuzzyBoolean.MAYBE;
		}
	}

	//如果返回值类型不是*,则对返回值类型进行匹配
	if (!returnType.isStar()) {
		boolean b = returnType.isBangVoid();
		if (b) {
			//如果表达式配置的匹配类型不是 void类型,而目标方法的类型是 Void 类型,则返回 NO
			String s = aMethod.getReturnType().getSignature();
			if (s.length() == 1 && s.charAt(0) == 'V') {
				return FuzzyBoolean.NO;
			}
		} else {
			//如果表达式配置的类型是 void 类型,而目标方法的类型不是 void类型,返回 NO
			if (returnType.isVoid()) {
				String s = aMethod.getReturnType().getSignature();
				if (s.length() != 1 || s.charAt(0) != 'V') {
					return FuzzyBoolean.NO;
				}
			} else {
				//如果表达式配置的方法返回值类型和目标方法返回值类型都不为空。则进行相关匹配,这下面考虑到泛型
				if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
					if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
						return FuzzyBoolean.MAYBE;
					}
				}
			}
		}
	}

	//如果表达式方法参数类型只有一个参数,并且是 .. ,则直接返回 YES
	if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {
		return FuzzyBoolean.YES;
	}
	//如果表达式配置的方法参数长度不等于目标方法参数个数时,返回 NO
	if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {
		return FuzzyBoolean.NO;
	}

	ResolvableTypeList rtl = new ResolvableTypeList(world, aMethod.getParameterTypes());
	//如果方法参数上有注解,则对每个方法参数上的注解进行获取
	ResolvedType[][] parameterAnnotationTypes = null;
	if (isMatchingParameterAnnotations()) {
		parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
		if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {
			parameterAnnotationTypes = null;
		}
	}
	//方法参数类型匹配
	if (!parameterTypes.matches(rtl, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {
		//方法参数类型匹配
		//如:表达式是这样配置 @Before("execution(* *(java.util.Map<com..Model, com..Model>, ..))") 
		// 将对(java.util.Map<com..Model, com..Model>, ..)中的每一项进行匹配,首先类型 java.util.Map,
		// 再是泛型com..Model 进行匹配,以及方法参数个数进行匹配 
		if (!parameterTypes.matches(new ResolvableTypeList(world, aMethod.getGenericParameterTypes()), TypePattern.STATIC,
				parameterAnnotationTypes).alwaysTrue()) {
			return FuzzyBoolean.MAYBE;
		}
	}

	//如果可变参数类型
	if (!matchesVarArgs(aMethod, world)) {
		return FuzzyBoolean.MAYBE;
	}

	return FuzzyBoolean.YES;
}

SignaturePattern.java

private boolean parametersCannotMatch(JoinPointSignature methodJoinpoint) {
	//如果目标方法是可变参数,直接返回 false
	if (methodJoinpoint.isVarargsMethod()) {
		return false;
	}
	//表达式中配置方法参数类型个数
	int patternParameterCount = parameterTypes.size();
	//如果表达式中方法参数个数为0或者没有配置省略号(..)
	if (patternParameterCount == 0 || parameterTypes.ellipsisCount == 0) {
		boolean equalCount = patternParameterCount == methodJoinpoint.getParameterTypes().length;

		//如果表达式中配置方法参数个数为0,但是目标方法参数个数不为0,返回 true 
		if (patternParameterCount == 0 && !equalCount) {
			return true;
		}

		//如果表达式中配置省略号个数为0 并且目标方法参数不等于表达式中配置参数个数
		if (parameterTypes.ellipsisCount == 0 && !equalCount) {
			//表达式中参数个数大于0,并且表达式中最后一个参数是可变参数,返回 false,匹配继续。
			if (patternParameterCount > 0 && parameterTypes.get(patternParameterCount - 1).isVarArgs()) {
				return false;
			}
			return true;
		}
	}
	return false;
}

在这个方法中,我们要注意的一点就是,返回 false,表示匹配继续,返回 true,表示匹配结束,表达式与方法不匹配。

TypePattern.java

public boolean matchesStatically(ResolvedType type) {
	if (includeSubtypes) {
		//如果表达式中包含+号,也就是包含子类型
		return matchesSubtypes(type);
	} else {
		return matchesExactly(type);
	}
}

WildTypePattern.java

protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
	String targetTypeName = type.getName();
	//确保注解模式己经解析
	annotationPattern.resolve(type.getWorld());
	//方法名称匹配
	return matchesExactlyByName(targetTypeName, type.isAnonymous(), type.isNested()) 
			//方法参数类型匹配
			&& matchesParameters(type, STATIC)
			//界线匹配
			&& matchesBounds(type, STATIC)
			//注解匹配
			&& annotationPattern.matches(annotatedType, type.temporaryAnnotationTypes).alwaysTrue();
}
private boolean matchesExactlyByName(String targetTypeName, boolean isAnonymous, boolean isNested) {
	//如果目标类型名称中有泛型
	if (targetTypeName.indexOf('<') != -1) {
		targetTypeName = targetTypeName.substring(0, targetTypeName.indexOf('<'));
	}
	//如果目标类型名称以?开头
	if (targetTypeName.startsWith(GENERIC_WILDCARD_CHARACTER)) {
		targetTypeName = GENERIC_WILDCARD_CHARACTER;
	}

	if (knownMatches == null && importedPrefixes == null) {
		return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
	}
	//如果配置的是*
	if (isNamePatternStar()) {
		int numDimensionsInTargetType = 0;
		//对于数组类型匹配
		if (dim > 0) {
			int index;
			while ((index = targetTypeName.indexOf('[')) != -1) {
				numDimensionsInTargetType++;
				targetTypeName = targetTypeName.substring(index + 1);
			}
			//如果表达式中配置的数组维数和目标方法中数组维数不一致,返回 false
			if (numDimensionsInTargetType == dim) {
				return true;
			} else {
				return false;
			}
		}
	}

	if (namePatterns.length == 1) {
		//匿名类型
		if (isAnonymous) {
			return false;
		}
		for (int i = 0, len = knownMatches.length; i < len; i++) {
			if (knownMatches[i].equals(targetTypeName)) {
				return true;
			}
		}
	} else {
		for (int i = 0, len = knownMatches.length; i < len; i++) {
			String knownMatch = knownMatches[i];
			//内部类相关处理
			if (targetTypeName.startsWith(knownMatch) && targetTypeName.length() > knownMatch.length()
					&& targetTypeName.charAt(knownMatch.length()) == '$') {
				int pos = lastIndexOfDotOrDollar(knownMatch);
				if (innerMatchesExactly(targetTypeName.substring(pos + 1), isAnonymous, isNested)) {
					return true;
				}
			}
		}
	}

	for (int i = 0, len = importedPrefixes.length; i < len; i++) {
		String prefix = importedPrefixes[i];
		//如果以 java.lang.开头
		if (targetTypeName.startsWith(prefix)) {
			if (innerMatchesExactly(targetTypeName.substring(prefix.length()), isAnonymous, isNested)) {
				return true;
			}
		}
	}

	return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
}
private boolean innerMatchesExactly(String s, boolean isAnonymous, boolean convertDollar /* isNested */) {
	//将表达式的包名和类名分割成 List 字符数组
	List<char[]> ret = new ArrayList<char[]>();
	int startIndex = 0;
	while (true) {
		int breakIndex = s.indexOf('.', startIndex); // what about /
		if (convertDollar && (breakIndex == -1)) {
			breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
		}
		if (breakIndex == -1) {
			break;
		}
		char[] name = s.substring(startIndex, breakIndex).toCharArray();
		ret.add(name);
		startIndex = breakIndex + 1;
	}
	ret.add(s.substring(startIndex).toCharArray());

	int namesLength = ret.size();
	int patternsLength = namePatterns.length;

	int namesIndex = 0;
	int patternsIndex = 0;

	if ((!namePatterns[patternsLength - 1].isAny()) && isAnonymous) {
		return false;
	}
	//如果名称和类名表达式中没有省略号【..】 
	if (ellipsisCount == 0) {
		if (namesLength != patternsLength) {
			return false;
		}
		while (patternsIndex < patternsLength) {
			//每个字符逐个匹配,如果匹配不成功,返回 false 
			if (!namePatterns[patternsIndex++].matches(ret.get(namesIndex++))) {
				return false;
			}
		}
		return true;
	} else if (ellipsisCount == 1) {////如果包名类型表达式中有一个省略号
		if (namesLength < patternsLength - 1) {
			return false;
		}
		while (patternsIndex < patternsLength) {
			NamePattern p = namePatterns[patternsIndex++];
			if (p == NamePattern.ELLIPSIS) {
				//跳过中间省略号
				namesIndex = namesLength - (patternsLength - patternsIndex);
			} else {
				//省略号前和省略号后逐个匹配,匹配不成功,返回 false。
				if (!p.matches(ret.get(namesIndex++))) {
					return false;
				}
			}
		}
		return true;
	} else {
		//如果有多个省略号的情况
		boolean b = outOfStar(namePatterns, ret.toArray(new char[ret.size()][]), 0, 0, patternsLength - ellipsisCount,
				namesLength, ellipsisCount);
		return b;
	}
}
public boolean matches(char[] a2) {
	char[] a1 = pattern;
	int len1 = a1.length;
	int len2 = a2.length;
	//如果字符数组中一个*都没有的情况
	if (starCount == 0) {
		//两字符串长度不相等,则肯定不匹配
		if (len1 != len2) {
			return false;
		}
		//否则,一个一个进行匹配
		for (int i = 0; i < len1; i++) {
			if (a1[i] != a2[i]) {
				return false;
			}
		}
		return true;
	} else if (starCount == 1) {		//如果表达式中有一个*号的情况
		if (len1 == 1) {
			return true;
		}
		//如果表达式中有*号,而且长度还大于目标方法字符数组,返回 false
		if (len1 > len2 + 1) {
			return false;
		}
		int i2 = 0;
		for (int i1 = 0; i1 < len1; i1++) {
			char c1 = a1[i1];
			//*吃掉多余字符
			if (c1 == '*') {
				i2 = len2 - (len1 - (i1 + 1));
			} else if (c1 != a2[i2++]) {//没有遇到*号时,逐个进行匹配,字符不相等,返回 false
				return false;
			}
		}
		return true;
	} else {
		//表达式中有多个*号的情况处理
		boolean b = outOfStar(a1, a2, 0, 0, len1 - starCount, len2, starCount);
		return b;
	}
}

在进行动态代理调用拦截器链时,发现下面的这个代码非常重要,因此,补一下这一块代码的解析,不过这一块代码以这个表达式为基础execution(* com.spring_1_100.test_61_70.test65_2..(…)) && args(x,y),使用的代码在 github 的 test65_2包下。

Pointcut.java

public final Test findResidue(Shadow shadow, ExposedState state) {
	//如果当前 shadow 己经被匹配过,将不再匹配
    Test ret = findResidueInternal(shadow, state);
    lastMatchedShadowId = shadow.shadowId;
    return ret;
}

AndPointcut.java

protected Test findResidueInternal(Shadow shadow, ExposedState state) {
	//根据表达式,execution(* com.spring_1_100.test_61_70.test65_4.*.*(..)) && args(x,y)
	//left 是execution(* com.spring_1_100.test_61_70.test65_4.*.*(..)) 表达式构建的 shadow
	//right是args(x,y)表达式构建的 shadow,左边表达式己经匹配过了,因此不再分析,右边表达式解析出来的PointCut 
	//类型是ArgsPointcut类,因此,其提供了自己findResidueInternal()方法。
    return Test.makeAnd(left.findResidue(shadow, state), right.findResidue(shadow, state));
}
public final Test findResidue(Shadow shadow, ExposedState state) {
    Test ret = findResidueInternal(shadow, state);
    lastMatchedShadowId = shadow.shadowId;
    return ret;
}

ArgsPointcut.java

protected Test findResidueInternal(Shadow shadow, ExposedState state) {
	//获取当前方法参数的ResolvedType[]类型
    ResolvedType[] argsToMatch = getArgumentsToMatchAgainst(shadow);
    //方法参数个数匹配,以及方法参数类型匹配,不匹配,返回 false
    if (arguments.matches(argsToMatch, TypePattern.DYNAMIC).alwaysFalse()) {
        return Literal.FALSE;
    }
    //表达式中方法参数配置省略号个数
    int ellipsisCount = arguments.ellipsisCount;
    if (ellipsisCount == 0) {//没有配置省略号
        return findResidueNoEllipsis(shadow, state, arguments.getTypePatterns());
    } else if (ellipsisCount == 1) {//配置1个省略号
        TypePattern[] patternsWithEllipsis = arguments.getTypePatterns();
        TypePattern[] patternsWithoutEllipsis = new TypePattern[argsToMatch.length];
        int lenWithEllipsis = patternsWithEllipsis.length;
        int lenWithoutEllipsis = patternsWithoutEllipsis.length;
        // l1+1 >= l0
        int indexWithEllipsis = 0;
        int indexWithoutEllipsis = 0;
        while (indexWithoutEllipsis < lenWithoutEllipsis) {
            TypePattern p = patternsWithEllipsis[indexWithEllipsis++];
            if (p == TypePattern.ELLIPSIS) {
                int newLenWithoutEllipsis = lenWithoutEllipsis - (lenWithEllipsis - indexWithEllipsis);
                while (indexWithoutEllipsis < newLenWithoutEllipsis) {
                    patternsWithoutEllipsis[indexWithoutEllipsis++] = TypePattern.ANY;
                }
            } else {
                patternsWithoutEllipsis[indexWithoutEllipsis++] = p;
            }
        }
        return findResidueNoEllipsis(shadow, state, patternsWithoutEllipsis);
    } else {
        throw new BCException("unimplemented");
    }
}
private Test findResidueNoEllipsis(Shadow shadow, ExposedState state, TypePattern[] patterns) {
    ResolvedType[] argumentsToMatchAgainst = getArgumentsToMatchAgainst(shadow);
    int len = argumentsToMatchAgainst.length;
    //如果方法参数个数和args()中目标方法配置参数个数不匹配,返回 false
    if (patterns.length != len) {
        return Literal.FALSE;
    }

    Test ret = Literal.TRUE;

    for (int i = 0; i < len; i++) {
        UnresolvedType argType = shadow.getGenericArgTypes()[i];
        TypePattern type = patterns[i];
        ResolvedType argRTX = shadow.getIWorld().resolve(argType, true);
       
        if (!(type instanceof BindingTypePattern)) {
        	//如果表达式解析出来的类型非BindingTypePattern类型
            if (argRTX.isMissing()) {
                shadow.getIWorld().getLint().cantFindType.signal(new String[] { WeaverMessages.format(
                        WeaverMessages.CANT_FIND_TYPE_ARG_TYPE, argType.getName()) }, shadow.getSourceLocation(),
                        new ISourceLocation[] { getSourceLocation() });
            }
            if (type.matchesInstanceof(argRTX).alwaysTrue()) {
                continue;
            }
        }

        World world = shadow.getIWorld();
        ResolvedType typeToExpose = type.getExactType().resolve(world);
        //如果表达式中配置类型是基本数据类型
        if (typeToExpose.isParameterizedType()) {
            boolean inDoubt = (type.matchesInstanceof(argRTX) == FuzzyBoolean.MAYBE);
            if (inDoubt && world.getLint().uncheckedArgument.isEnabled()) {
                String uncheckedMatchWith = typeToExpose.getSimpleBaseName();
                if (argRTX.isParameterizedType() && (argRTX.getRawType() == typeToExpose.getRawType())) {
                    uncheckedMatchWith = argRTX.getSimpleName();
                }
                if (!isUncheckedArgumentWarningSuppressed()) {
                    world.getLint().uncheckedArgument.signal(new String[] { typeToExpose.getSimpleName(), uncheckedMatchWith,
                            typeToExpose.getSimpleBaseName(), shadow.toResolvedString(world) }, getSourceLocation(),
                            new ISourceLocation[] { shadow.getSourceLocation() });
                }
            }
        }
		
        ret = Test.makeAnd(ret, exposeStateForVar(shadow.getArgVar(i), type, state, shadow.getIWorld()));
    }

    return ret;
}

NameBindingPointcut.java

protected Test exposeStateForVar(Var var,TypePattern type, ExposedState state, World world) {
    if (type instanceof BindingTypePattern) {
        BindingTypePattern b = (BindingTypePattern)type;
        //设置目标方法的实际类型
        state.set(b.getFormalIndex(), var);
    }
    ResolvedType myType = type.getExactType().resolve(world);
    //如果是基本数据类型
    if (myType.isParameterizedType()) {
        myType = (ResolvedType) myType.getRawType();
    }
    //判断目标方法参数的实际类型与表达式所配置的类型是否一致
    return Test.makeInstanceof(var, myType.resolve(world));
}

Test.java

public static Test makeInstanceof(Var v, ResolvedType ty) {
    if (ty.equals(ResolvedType.OBJECT)) return Literal.TRUE;
    Test e;
    if (ty.isAssignableFrom(v.getType())) e = Literal.TRUE;
    else if (! ty.isCoerceableFrom(v.getType())) e = Literal.FALSE;
    else e = new Instanceof(v, ty);
    return e;
}

最终将返回的 Test 对象保存到ShadowMatchImpl.residualTest属性中。

流程:

 1)canApply() :是否符合切面条件
 	1)getClassFilter().matches(): 类是否匹配
 	2)methodMatcher.matches(): 方法是否匹配
 		1) checkReadyToMatch(): 简单的较验
 		2) getMostSpecificMethod(): 获取当前拦截类的方法
 			1)getMostSpecificMethod() :当如果调用的当前方法不是自己类的方法,是父类中继承来的方法,将匹配到父类中方法。
 				1)getMethod0() :获取方法。
 					1)privateGetMethodRecursive(): 递归获取方法
 						1)privateGetDeclaredMethods() : 获取该类或接口的所有的方法
 							1)searchMethods(): 搜索合适的方法
 						2)getSuperclass():如果本类中没有搜索到匹配的方法,到父类中查找
 							1)getMethod0():递归调用父类的获取方法
 						3) getInterfaces(): 如果本类或者父类中没有找到,获取该类的所有接口,这种情况,只有在 jdk1.8中才支持,在接口中定义默认方法。
 							1)getMethod0(): 递归获取接口中合适的方法。
 		3)getShadowMatch():获取ShadowMatch匹配
 			1)matchesMethodExecution():匹配方法执行
 				1)matchesExecution(): 匹配执行
 					1)makeExecutionShadow():
	 					1)createResolvedMember(): 创建Member
	 						1)createResolvedMethod():创建ResolvedMember
	 							1)new ReflectionBasedResolvedMemberImpl(): 创建反射 Member 类
	 								1) this.kind: 初始化当前类型为METHON
	 								2) this.declaringType:当前方法类型com.spring_101_200.test_111_120.test_117_excution.excution1.MyService
									3) this.modifiers: 当前方法修饰符
									4) this.returnType: 设置返回值类型
									5) this.name:方法名称
									6) this.parameterTypes:设置方法参数类型
									7) this.erasedSignature:方法的返回值的字节码常量池的表示方法 ,如()V 
									8) this.checkedExceptions:设置异常较验。
									9) this.reflectMember: 设置方法的 Member 类型
									10) this.annotationFinder:设置注解发现器Java15AnnotationFinder
									11) setGenericSignatureInformationProvider():设置Java15GenericSignatureInformationProvider
	 						2)new ReflectionShadow():创建ReflectionShadow
 					2)getShadowMatch(): 获取匹配的实现类
 						1)match(): 开始匹配
 							1)matchInternal():真正匹配
 								1)matches(): 是否匹配signature
 									1)matchesExactly(): 精确匹配
 										1)modifiers.matches():  方法修饰符匹配,如果不匹配,返回 false 。
 										2)matchesExactlyMethod(): 方法精确匹配
 											1) parametersCannotMatch(): 参数匹配。
 											2) name.matches():方法名称匹配。
 											3) throwsPattern.matches(): 异常类型匹配。不匹配返回 NO
 											4)declaringType.matchesStatically():包,类,匹配。
 												1)matchesExactly():   do 包,类匹配
 													1)matchesExactlyByName(): 通过包名,类名,方法名匹配。
 														1)innerMatchesExactly():具体匹配
 															1)namePatterns[patternsIndex++].matches(ret.get(namesIndex++)) :匹配每一个包名,类名,以及方法名。
 													2)matchesParameters(): 方法参数类型匹配。
 													3)matchesBounds(): 有界引用类型匹配。
 													4)annotationPattern.matches() :方法注解类型匹配。
 											5)returnType.matchesStatically():返回值类型匹配
 											6)parameterTypes.count() : 参数个数匹配 
 								2)匹配成功返回 true,匹配失败返回 false。				

到这里,我们己经解析完成,来总结一下,其实切面表达式的匹配过程非常的繁琐,但是又每一步必不可少,切面表达式在解析时就确定当前表达式是哪个 PointCut,在匹配时,就调用哪一个 PointCut的 matches 方法。这种策略模式,将复杂表达式清淅的在规律的分布在Spring代码的各个角落。从而实现了表达式的解析和匹配。下面我们来具体的分析一下整个匹配流程。

1.根据目标方法找到最合适的方法,假如切面表达式限制只能 com.a 包下的方法才被拦截,而此时com.a.A继承 com.b.B 类
	com.b.B 中有 test()方法,此时调用com.a.A.test()方法,因为 test()方法是 A 类从 B 类中继承而来,方法属于 
	com.b包下的方法,因此,而此时切面只拦截 com.a 包下的所有方法,因此,此时调用 com.a.A().test()方法,将不被拦截。
2.封装ReflectionShadow对象,将从切面表达式中解析出来的方法修饰,返回值,方法注解,包名类名,方法名,方法参数类	
	型,方法参数个数,方法注解类型,等等,封装到ReflectionShadow对象。
3.目标方法和切面表达式匹配:将目标方法的每一项和方法的每一项进行匹配,只要匹配失败,返回 NO。

在具体去分析某个具体的 Spring 示例时,会觉得 Spring 的博大精深,大到架构,小到字符串匹配,都透露着高明之处,而且无论你怎样复杂的表达式,都会被解析完成,因为里面用了大量的递归调用,相当于孙猴子无论如何都跳不出如来的五指山一样,非常的值得学习,有兴趣的小伙伴还是自己打断点,自行研究一下吧。相信你有意想不到的收获。如果你专心看完这篇博客时,那来思考一下下面的问题?

思考?

User.java

@MyAnnotation
public class User {
}

Model.java

public class Model implements Serializable {

}

MyAnnotation.java

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.PARAMETER,ElementType.FIELD})
@Documented
public @interface MyAnnotation {
    String value() default "";
}

UserService.java

public interface UserService {
    void testModel(Map

UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {

    @Override
    public void testModel(Map<Model, Model> modelMap, String a) {
        System.out.println("testModel");
    }

    @Override
    public void testModel1(String a, Map<Model, Model> modelMap) {
        System.out.println("testModel1");
    }

    @Override
    public void testModel2(Map modelMap, String a) {
        System.out.println("testModel2");
    }
}

AspectJTest.java

public class AspectJTest {
    @Before("execution(* *(@com..MyAnnotation (@com..MyService *),@com..MyAnnotation (@com..MyService  *)))")
    public void beforeTest() {
        System.out.println("beforeTest");
    }
}

测试:

public void test17() throws Exception {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_101_200/config_111_120/spring117_excution/spring_117_excution17.xml");
    System.out.println("============================");
    UserService userService = ac.getBean(UserService.class);
    userService.getUserHomeWork(new User(), new User());
    System.out.println("=============================");
    userService.getUserHomeInfo(new User(), new User());
    System.out.println("=============================");
    userService.getModelInfo(new Model(), new Model());
}

结果?

感兴趣的小伙伴,去研究一下,为什么是这样的输出结果?

本文的github地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_101_200/test_111_120/test_117_excution/excution1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值