当前位置: 首页> 文旅> 艺术 > 腾讯云域名查询_网页建设的公司_网络营销环境分析_杭州网站推广大全

腾讯云域名查询_网页建设的公司_网络营销环境分析_杭州网站推广大全

时间:2025/7/14 20:49:50来源:https://blog.csdn.net/zlk252620068/article/details/142589717 浏览次数:0次
腾讯云域名查询_网页建设的公司_网络营销环境分析_杭州网站推广大全

我们知道,在 AspectJ 中配置切点表达时,需配置全限定性类名,但对于 java.lang.String 可以简化为 String,直接配置,这是怎么实现的呢?这就涉及到了 AspectJ 中的类型绑定机制。

示例一

"execution(* *..UserServiceImpl.doSome(String...,int))"

我们知道,在 Java 的语法中,可变参数只能放在形参的最后,并且每个方法只能有一个可变参数,但是在 AspectJ 的切入点表达式解析规则中,上面的配置是可以解析的。

参数解析

在 org.aspectj.weaver.patterns.PatternParser#parseMethodOrConstructorSignaturePattern 方法中,会执行 parseArgumentsPattern,解析得到参数的匹配模式。

// 解析参数类型时,以 "," 作为类型分割,每个类型单独解析
public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {List<TypePattern> patterns = new ArrayList<>();eat("(");// ()if (maybeEat(")")) {return new TypePatternList();}do {if (maybeEat(".")) { // ..eat(".");patterns.add(TypePattern.ELLIPSIS);} else {patterns.add(parseTypePattern(false, parameterAnnotationsPossible));}} while (maybeEat(","));eat(")");return new TypePatternList(patterns);
}

解析参数类型时,以 "," 作为类型分割,每个类型单独解析。(String...,int) 被解析成了两个 TypePattern,"String..." 和 "int",最后封装成 TypePatternList。

public TypePattern parseTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {TypePattern p = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);if (maybeEat("&&")) {p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters, parameterAnnotationsPossible));}if (maybeEat("||")) {p = new OrTypePattern(p, parseTypePattern(insideTypeParameters, parameterAnnotationsPossible));}return p;
}

可以看到,转换成了类型解析,执行 parseAtomicTypePattern --> parseSingleTypePattern

// insideTypeParameters false
public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {if (insideTypeParameters && maybeEat("?")) {return parseGenericsWildcardTypePattern();}if (allowHasTypePatterns) {if (maybeEatIdentifier("hasmethod")) {return parseHasMethodTypePattern();}if (maybeEatIdentifier("hasfield")) {return parseHasFieldTypePattern();}}if (maybeEatIdentifier("is")) {int pos = tokenSource.getIndex() - 1;TypePattern typeIsPattern = parseIsTypePattern();if (typeIsPattern != null) {return typeIsPattern;}// rewind as if we never tried to parse it as a typeIstokenSource.setIndex(pos);}// 按 "." 解析成 NamePattern 集合List<NamePattern> names = parseDottedNamePattern();int dim = 0;while (maybeEat("[")) {eat("]");dim++;}TypePatternList typeParameters = maybeParseTypeParameterList();int endPos = tokenSource.peek(-1).getEnd();boolean includeSubtypes = maybeEat("+");// TODO do we need to associate the + with either the type or the array?while (maybeEat("[")) {eat("]");dim++;}boolean isVarArgs = maybeEat("...");// ??? what about the source location of any's????if (names.size() == 1 && names.get(0).isAny() && dim == 0 && !isVarArgs && typeParameters == null) {return TypePattern.ANY;}// Notice we increase the dimensions if varargs is set. this is to allow type matching to// succeed later: The actual signature at runtime of a method declared varargs is an array type of// the original declared type (so Integer... becomes Integer[] in the bytecode). So, here for the// pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set. If this matches// during shadow matching, we confirm that the varargs flags match up before calling it a successful// match.return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs, typeParameters);
}public List<NamePattern> parseDottedNamePattern() {List<NamePattern> names = new ArrayList<>();StringBuffer buf = new StringBuffer();IToken previous = null;boolean justProcessedEllipsis = false; // Remember if we just dealt with an ellipsis (PR61536)boolean justProcessedDot = false;boolean onADot = false;while (true) {IToken tok = null;int startPos = tokenSource.peek().getStart();String afterDot = null;while (true) {if (previous != null && previous.getString().equals(".")) {justProcessedDot = true;}tok = tokenSource.peek();onADot = (tok.getString().equals("."));if (previous != null) {if (!isAdjacent(previous, tok)) {break;}}// "..." 也是标识符,但 "<" 不是if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString() != "...")) {buf.append(tok.getString());} else if (tok.getString() == "...") {break;// literalKind 为 null,直接 break 退出内循环} else if (tok.getLiteralKind() != null) {// System.err.println("literal kind: " + tok.getString());String s = tok.getString();int dot = s.indexOf('.');if (dot != -1) {buf.append(s.substring(0, dot));afterDot = s.substring(dot + 1);previous = tokenSource.next();break;}buf.append(s); // ??? so-so} else {break;}previous = tokenSource.next();// XXX need to handle floats and other fun stuff}int endPos = tokenSource.peek(-1).getEnd();if (buf.length() == 0 && names.isEmpty()) {throw new ParserException("name pattern", tok);}if (buf.length() == 0 && justProcessedEllipsis) {throw new ParserException("name pattern cannot finish with ..", tok);}if (buf.length() == 0 && justProcessedDot && !onADot) {throw new ParserException("name pattern cannot finish with .", tok);}if (buf.length() == 0) {names.add(NamePattern.ELLIPSIS);justProcessedEllipsis = true;} else {checkLegalName(buf.toString(), previous);NamePattern ret = new NamePattern(buf.toString());ret.setLocation(sourceContext, startPos, endPos);names.add(ret);justProcessedEllipsis = false;}if (afterDot == null) {buf.setLength(0);// no elipsis or dotted name partif (!maybeEat(".")) {break;// go on} else {previous = tokenSource.peek(-1);}} else {buf.setLength(0);buf.append(afterDot);afterDot = null;}}// System.err.println("parsed: " + names);return names;
}

执行 parseDottedNamePattern,按 "." 解析成 NamePattern 集合,也就是将包名和类名按 "." 拆分成单独的部分。对于示例参数类型 "String...",由于未指定包名,解析后 NamePattern 集合 names 中只有一个元素,即 "String"。

接着,由于存在 "...",isVarArgs 为 true。

注意,在配置的切入点表达式中,".." 和 "..." 的含义是不同的。

".."按省略号对待,解析后 ellipsisCount 数量会增加,用在方法参数中,表示任意个参数且参数类型不限
"..."标识符,可变参数,实际解析时按指定类型的数组类型对待

处理完以上的解析点之后,将类型封装为 WildTypePattern。 

WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs, TypePatternList typeParams) {super(includeSubtypes, isVarArgs, typeParams);this.namePatterns = namePatterns;this.dim = dim;ellipsisCount = 0;for (NamePattern namePattern : namePatterns) {if (namePattern == NamePattern.ELLIPSIS) {ellipsisCount++;}}setLocation(namePatterns[0].getSourceContext(), namePatterns[0].getStart(), namePatterns[namePatterns.length - 1].getEnd());
}
protected TypePattern(boolean includeSubtypes, boolean isVarArgs, TypePatternList typeParams) {this.includeSubtypes = includeSubtypes;this.isVarArgs = isVarArgs;this.typeParameters = (typeParams == null ? TypePatternList.EMPTY : typeParams);
}

可以看到封装的 WildTypePattern 将 namePatterns 和 typeParameters 分开了,namePatterns 只包含类型定义。 

类型绑定

解析完之后,得到 Pointcut,接着构建一个解析范围,也就是 @Aspect 切面类,切点表达式定义在切面类中。

// Pointcut
public final Pointcut resolve(IScope scope) {assertState(SYMBOLIC);// scope.getFormalCount() 获取的就是用户在切面方法上显式指定的参数数量Bindings bindingTable = new Bindings(scope.getFormalCount());IScope bindingResolutionScope = scope;if (typeVariablesInScope.length > 0) {bindingResolutionScope = new ScopeWithTypeVariables(typeVariablesInScope, scope);}this.resolveBindings(bindingResolutionScope, bindingTable);bindingTable.checkAllBound(bindingResolutionScope);this.state = RESOLVED;return this;
}

执行 resolveBindings 就是进行类型的解析绑定。

在 KindedPointcut#resolveBindings 中,执行 signature.resolveBindings(scope, bindings)。

// SignaturePattern
@Override
public SignaturePattern resolveBindings(IScope scope, Bindings bindings) {if (returnType != null) {returnType = returnType.resolveBindings(scope, bindings, false, false);checkForIncorrectTargetKind(returnType, scope, false);}if (declaringType != null) {declaringType = declaringType.resolveBindings(scope, bindings, false, false);checkForIncorrectTargetKind(declaringType, scope, false);isExactDeclaringTypePattern = (declaringType instanceof ExactTypePattern);}if (parameterTypes != null) {parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false);checkForIncorrectTargetKind(parameterTypes, scope, false, true);}if (throwsPattern != null) {throwsPattern = throwsPattern.resolveBindings(scope, bindings);if (throwsPattern.getForbidden().getTypePatterns().length > 0|| throwsPattern.getRequired().getTypePatterns().length > 0) {checkForIncorrectTargetKind(throwsPattern, scope, false);}}if (annotationPattern != null) {annotationPattern = annotationPattern.resolveBindings(scope, bindings, false);checkForIncorrectTargetKind(annotationPattern, scope, true);}hashcode = -1;return this;
}

可以看到,分别针对返回值类型,方法定义类型、参数类型、异常类型、注解类型进行了绑定。我们主要来看下参数绑定。

上面的 parameterTypes,其实就是方法参数解析之后封装的 TypePatternList。

// TypePatternList
public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {for (int i = 0; i < typePatterns.length; i++) {TypePattern p = typePatterns[i];if (p != null) {typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding, requireExactType);}}return this;
}

遍历每一个类型对应的 TypePattern,逐个进行绑定。除 "*" 外,其余的类型在切入点表达式解析时都会被解析为 WildTypePattern,所以此处会执行 WildTypePattern#resolveBindings 进行类型的绑定。

// WildTypePattern
@Override
public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {// NamePattern 是 "*"if (isNamePatternStar()) {TypePattern anyPattern = maybeResolveToAnyPattern(scope, bindings, allowBinding, requireExactType);if (anyPattern != null) {if (requireExactType) {scope.getWorld().getMessageHandler().handleMessage(MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));return NO;} else {return anyPattern;}}}// 返回 nullTypePattern bindingTypePattern = maybeResolveToBindingTypePattern(scope, bindings, allowBinding, requireExactType);if (bindingTypePattern != null) {return bindingTypePattern;}annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);// resolve any type parameters// 类型泛型参数// 先对泛型参数类型进行绑定if (typeParameters != null && typeParameters.size() > 0) {typeParameters.resolveBindings(scope, bindings, allowBinding, requireExactType);isGeneric = false;}// resolve any boundsif (upperBound != null) {upperBound = upperBound.resolveBindings(scope, bindings, allowBinding, requireExactType);}if (lowerBound != null) {lowerBound = lowerBound.resolveBindings(scope, bindings, allowBinding, requireExactType);// amc - additional interface bounds only needed if we support type vars again.}// 获取全限定性类名String fullyQualifiedName = maybeGetCleanName();  // String// 全限定性类名不为 null,才执行绑定if (fullyQualifiedName != null) {return resolveBindingsFromFullyQualifiedTypeName(fullyQualifiedName, scope, bindings, allowBinding, requireExactType);} else {if (requireExactType) {scope.getWorld().getMessageHandler().handleMessage(MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));return NO;}importedPrefixes = scope.getImportedPrefixes();knownMatches = preMatch(scope.getImportedNames());return this; // pattern contains wildcards so can't be resolved to an ExactTypePattern...// XXX need to implement behavior for Lint.invalidWildcardTypeName}
}
private TypePattern maybeResolveToBindingTypePattern(IScope scope, Bindings bindings, boolean allowBinding,boolean requireExactType) {// namePatterns 长度为 1,获取 simpleName // 例如 int 类型String simpleName = maybeGetSimpleName();if (simpleName != null) {// scope 为 BindingScope,继承 SimpleScope// 返回 nullFormalBinding formalBinding = scope.lookupFormal(simpleName); // nullif (formalBinding != null) {if (bindings == null) {scope.message(IMessage.ERROR, this, "negation doesn't allow binding");return this;}if (!allowBinding) {scope.message(IMessage.ERROR, this, "name binding only allowed in target, this, and args pcds");return this;}BindingTypePattern binding = new BindingTypePattern(formalBinding, isVarArgs);binding.copyLocationFrom(this);bindings.register(binding, scope);return binding;}}return null; // not possible to resolve to a binding type pattern
}

由外部传入的 parameterNames 和 parameterTypes 封装的 org.aspectj.weaver.tools.PointcutParameter 数组,在构建 IScope 时,解析为 FormalBinding 数组,封装在 IScope 的实现类 BindingScope 中。执行 scope.lookupFormal(simpleName) 时,遍历 FormalBinding 数组,判断 FormalBinding 数组元素持有的 name 是否和 simpleName 相等,相等则将当前 FormalBinding 返回。外部未传入 parameterNames 和 parameterTypes 时,执行 maybeResolveToBindingTypePattern 返回 null。我们在前面的文章                                         《AspectJ 中通知方法参数绑定》中介绍过,显式指定的参数在之后的 checkAllBound 方法执行时都会抛出异常,所以使用时不会自定义显式参数,即此处恒返回 null。

有一点注意,当获取全限定性类名 fullyQualifiedName 时,如果配置的表达式中表示类型的部分含有 "*",则表示不确定,获取的 fullyQualifiedName 为 null。只有 fullyQualifiedName 不为 null,才会执行真正的绑定。否则,会将原 WildTypePattern 返回。

// WildTypePattern
private TypePattern resolveBindingsFromFullyQualifiedTypeName(String fullyQualifiedName, IScope scope, Bindings bindings,boolean allowBinding, boolean requireExactType) {String originalName = fullyQualifiedName;ResolvedType resolvedTypeInTheWorld = null;UnresolvedType type;// System.out.println("resolve: " + cleanName);// ??? this loop has too many inefficiencies to countresolvedTypeInTheWorld = lookupTypeInWorldIncludingPrefixes(scope.getWorld(), fullyQualifiedName, scope.getImportedPrefixes());if (resolvedTypeInTheWorld.isGenericWildcard()) {type = resolvedTypeInTheWorld;} else {type = lookupTypeInScope(scope, fullyQualifiedName, this);}// 在 scope 中未找到if ((type instanceof ResolvedType) && ((ResolvedType) type).isMissing()) {return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding,requireExactType);} else {// scope 中找到,解析绑定的确切类型return resolveBindingsForExactType(scope, type, fullyQualifiedName, requireExactType);}
}
private ResolvedType lookupTypeInWorldIncludingPrefixes(World world, String typeName, String[] prefixes) {ResolvedType ret = lookupTypeInWorld(world, typeName); // Stringif (!ret.isMissing()) {return ret;}ResolvedType retWithPrefix = ret;int counter = 0;// 丢失了,加上前缀接着找,默认的前缀一个 "java.lang.",找到了,退出循环,此时 retWithPrefix 为 ReferenceTypewhile (retWithPrefix.isMissing() && (counter < prefixes.length)) {retWithPrefix = lookupTypeInWorld(world, prefixes[counter] + typeName);counter++;}// 找到了,将 retWithPrefix 返回if (!retWithPrefix.isMissing()) {return retWithPrefix;}return ret;
}
private ResolvedType lookupTypeInWorld(World world, String typeName) {UnresolvedType ut = UnresolvedType.forName(typeName);   // signature = "LString;"    -->  new UnresolvedType(signature);ResolvedType ret = world.resolve(ut, true);  // 调用 World#resolve --> World#resolveToReferenceType// ret 为 MissingResolvedTypeWithKnownSignature 时,isMissing() 返回 truewhile (ret.isMissing()) {int lastDot = typeName.lastIndexOf('.');// "String" 跳出循环if (lastDot == -1) {break;}// 内部类typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);ret = world.resolve(UnresolvedType.forName(typeName), true);}return ret;
}

在 lookTypeInWorldIncludingPrefixes 中,先对确定的全限定性类名,即 typeName,执行 lookupTypeInWorld,其实就是利用传入的 World,对 typeName 进行解决。

scope.getImportedPrefixes(),在 SimpleScope 中,默认 importedPrefixes 为 "java.lang."。

当 typeName 为 "String" 时,执行 WildTypePattern#lookupTypeInWorld,在方法中,利用 World 将 ut 处理为 ResolvedType。

public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) {// special resolution processing for already resolved types.if (ty instanceof ResolvedType) {ResolvedType rty = (ResolvedType) ty;rty = resolve(rty);// A TypeVariableReferenceType may look like it is resolved (it extends ResolvedType) but the internal// type variable may not yet have been resolvedif (!rty.isTypeVariableReference() || ((TypeVariableReferenceType) rty).isTypeVariableResolved()) {return rty;}}// dispatch back to the type variable reference to resolve its// constituent parts don't do this for other unresolved types otherwise// you'll end up in a// loopif (ty.isTypeVariableReference()) {return ty.resolve(this);}// if we've already got a resolved type for the signature, just return// it// after updating the worldString signature = ty.getSignature();ResolvedType ret = typeMap.get(signature);if (ret != null) {ret.world = this; // Set the world for the RTXreturn ret;} else if (signature.equals("?") || signature.equals("*")) {// might be a problem here, not sure '?' should make it to here as a// signature, the// proper signature for wildcard '?' is '*'// fault in generic wildcard, can't be done earlier because of init// issues// TODO ought to be shared single instance representing thisResolvedType something = getWildcard();typeMap.put("?", something);return something;}// no existing resolved type, create onesynchronized (buildingTypeLock) {if (ty.isArray()) {ResolvedType componentType = resolve(ty.getComponentType(), allowMissing);ret = new ArrayReferenceType(signature, "[" + componentType.getErasureSignature(), this, componentType);} else {ret = resolveToReferenceType(ty, allowMissing);if (!allowMissing && ret.isMissing()) {ret = handleRequiredMissingTypeDuringResolution(ty);}if (completeBinaryTypes) {completeBinaryType(ret);}}}// Pulling in the type may have already put the right entry in the mapResolvedType result = typeMap.get(signature);if (result == null && !ret.isMissing()) {ret = ensureRawTypeIfNecessary(ret);typeMap.put(signature, ret);return ret;}if (result == null) {return ret;} else {return result;}
}
// World
// 解析为 ReferenceType
private final ResolvedType resolveToReferenceType(UnresolvedType ty, boolean allowMissing) {if (ty.isParameterizedType()) {// ======= parameterized types ================ResolvedType rt = resolveGenericTypeFor(ty, allowMissing);if (rt.isMissing()) {return rt;}ReferenceType genericType = (ReferenceType) rt;ReferenceType parameterizedType = TypeFactory.createParameterizedType(genericType, ty.typeParameters, this);return parameterizedType;} else if (ty.isGenericType()) {// ======= generic types ======================ResolvedType rt = resolveGenericTypeFor(ty, false);if (rt.isMissing()) {return rt;}ReferenceType genericType = (ReferenceType) rt;if (rt.isMissing()) {return rt;}return genericType;} else if (ty.isGenericWildcard()) {// ======= generic wildcard types =============return resolveGenericWildcardFor((WildcardedUnresolvedType) ty);} else {// ======= simple and raw types ===============// 获取泛型擦除后的签名字符串String erasedSignature = ty.getErasureSignature();ReferenceType simpleOrRawType = new ReferenceType(erasedSignature, this);if (ty.needsModifiableDelegate()) {simpleOrRawType.setNeedsModifiableDelegate(true);}// 针对 "String" 创建 delegate 时,利用 ClassLoader 加载 "String",无法加载,返回 nullReferenceTypeDelegate delegate = resolveDelegate(simpleOrRawType);if (delegate == null) {// MissingResolvedTypeWithKnownSignature 继承 ResolvedType,ResolvedType 继承 UnresolvedTypereturn new MissingResolvedTypeWithKnownSignature(ty.getSignature(), erasedSignature, this);}if (delegate.isGeneric() && behaveInJava5Way) {// ======== raw type ===========simpleOrRawType.typeKind = TypeKind.RAW;if (simpleOrRawType.hasNewInterfaces()) { // debug 375777throw new IllegalStateException("Simple type promoted forced to raw, but it had new interfaces/superclass.  Type is "+ simpleOrRawType.getName());}ReferenceType genericType = makeGenericTypeFrom(delegate, simpleOrRawType);simpleOrRawType.setDelegate(delegate);genericType.setDelegate(delegate);simpleOrRawType.setGenericType(genericType);return simpleOrRawType;} else {// ======== simple type =========simpleOrRawType.setDelegate(delegate);return simpleOrRawType;}}
}

将 UnresolvedType 解析为 ReferenceType 之后,会为其创建一个 delegate。

public static ReflectionBasedReferenceTypeDelegate createDelegate(ReferenceType forReferenceType, World inWorld,ClassLoader usingClassLoader) {try {Class c = Class.forName(forReferenceType.getName(), false, usingClassLoader);ReflectionBasedReferenceTypeDelegate rbrtd = create15Delegate(forReferenceType, c, usingClassLoader, inWorld);if (rbrtd != null) {return rbrtd; // can be null if we didn't find the class the delegate logic loads}return new ReflectionBasedReferenceTypeDelegate(c, usingClassLoader, inWorld, forReferenceType);} catch (ClassNotFoundException cnfEx) {return null;}
}private static ReflectionBasedReferenceTypeDelegate create15Delegate(ReferenceType forReferenceType, Class forClass,ClassLoader usingClassLoader, World inWorld) {try {Class delegateClass = Class.forName("org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate");ReflectionBasedReferenceTypeDelegate ret = (ReflectionBasedReferenceTypeDelegate) delegateClass.getDeclaredConstructor().newInstance();ret.initialize(forReferenceType, forClass, usingClassLoader, inWorld);return ret;} catch (ClassNotFoundException cnfEx) {throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate was not found on classpath");} catch (InstantiationException insEx) {throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but InstantiationException: "+ insEx + " occured");} catch (IllegalAccessException illAccEx) {throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but IllegalAccessException: "+ illAccEx + " occured");} catch (NoSuchMethodException nsMethEx) {throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but NoSuchMethodException: "+ nsMethEx + " occured");} catch (InvocationTargetException invTargEx) {throw new IllegalStateException("Attempted to create Java 1.5 reflection based delegate but InvocationTargetException: "+ invTargEx + " occured");}
}

利用 classLoader 去加载 "String",此时捕获异常,返回 null,由于 delegate 为 null,会创建一个 MissingResolvedTypeWithKnownSignature 返回。MissingResolvedTypeWithKnownSignature 继承 ResolvedType。

MissingResolvedTypeWithKnownSignature#isMissing 返回 true,此时在 lookupTypeInWorldIncludingPrefixes 方法中,遍历 prefixes 数组,给无法加载的类型,加上前缀接着执行 lookupTypeInWorld 去查找,"String" 变成 "java.lang.String",这一次可以加载。利用反射创建一个 Java15ReflectionBasedReferenceTypeDelegate,并完成初始化。之后为 simpleOrRawType 设置 delegate 之后返回,接着退出循环,此时 retWithPrefix 为 ReferenceType。

接着,由于 resolvedTypeInTheWorld.isGenericWildcard() 返回 false,执行 lookupTypeInScope,在 scope 中再查找一遍。

// WildTypePattern
// 此处参数 loacation,即 WildTypePattern
private UnresolvedType lookupTypeInScope(IScope scope, String typeName, IHasPosition location) {UnresolvedType type = null;while (ResolvedType.isMissing(type = scope.lookupType(typeName, location))) {  // typeName "String"int lastDot = typeName.lastIndexOf('.');if (lastDot == -1) {break;}typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);}return type;
}
// BindingsScope
public UnresolvedType lookupType(String name, IHasPosition location) {// 扩展 importedPrefixes// bug 126560if (enclosingType != null && !importsUpdated) {// add the package we're in to the list of imported// prefixes so that we can find types in the same packageString pkgName = enclosingType.getPackageName();  // 切面类包名if (pkgName != null && !pkgName.equals("")) {String[] existingImports = getImportedPrefixes();  // {"java.lang."}String pkgNameWithDot = pkgName.concat(".");  // pkgName + "."boolean found = false;for (String existingImport : existingImports) {if (existingImport.equals(pkgNameWithDot)) {found = true;break;}}// 变更 SimpleScope 中 importedPrefixesif (!found) {String[] newImports = new String[existingImports.length + 1];System.arraycopy(existingImports, 0, newImports, 0, existingImports.length);newImports[existingImports.length] = pkgNameWithDot;setImportedPrefixes(newImports);}}importsUpdated = true;}return super.lookupType(name, location);
}
// BindingScope 父类 SimpleScope
public UnresolvedType lookupType(String name, IHasPosition location) {for (String importedName : importedNames) {  // {}// make sure we're matching against the type name rather than part of it// if (importedName.endsWith("." + name)) {if (importedName.endsWith(name)) {return world.resolve(importedName);}}// Check for a primitiveif (name.length() < 8 && Character.isLowerCase(name.charAt(0))) {// could be a primitiveint len = name.length();if (len == 3) {if (name.equals("int")) {return UnresolvedType.INT;}} else if (len == 4) {if (name.equals("void")) {return UnresolvedType.VOID;} else if (name.equals("byte")) {return UnresolvedType.BYTE;} else if (name.equals("char")) {return UnresolvedType.CHAR;} else if (name.equals("long")) {return UnresolvedType.LONG;}} else if (len == 5) {if (name.equals("float")) {return UnresolvedType.FLOAT;} else if (name.equals("short")) {return UnresolvedType.SHORT;}} else if (len == 6) {if (name.equals("double")) {return UnresolvedType.DOUBLE;}} else if (len == 7) {if (name.equals("boolean")) {return UnresolvedType.BOOLEAN;}}}// Is it fully qualified?// 全类型指定,直接解析if (name.indexOf('.') != -1) {return world.resolve(UnresolvedType.forName(name), true);}// 遍历前缀,加前缀解析for (String importedPrefix : importedPrefixes) {ResolvedType tryType = world.resolve(UnresolvedType.forName(importedPrefix + name), true);if (!tryType.isMissing()) {return tryType;}}return world.resolve(UnresolvedType.forName(name), true);
}

可以看到,先对默认的 importedPrefixes 进行了扩充,将切面类所在包名也扩充了进去。接着执行 SimpleScope#lookupType,对基本类型和全限定类型,单独处理,针对 "String",会加上前缀进行解析,解析为 ReferenceType,直接返回。此处执行 world.resolve 时,如果之前已经对相应类型进行过解析,则会直接从 World 中的缓存字段 typeMap 中获取到对应的 ResolvedType。

由于已经判断为确定的类型,接下来执行绑定的最后一步,调用 WildTypePattern#resolveBindingsForExactType,封装 ExactTypePattern

// WildTypePattern
private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName,boolean requireExactType) {TypePattern ret = null;if (aType.isTypeVariableReference()) {// we have to set the bounds on it based on the bounds of this patternret = resolveBindingsForTypeVariable(scope, (UnresolvedTypeVariableReferenceType) aType);} else if (typeParameters.size() > 0) {// 存在泛型参数时处理方式ret = resolveParameterizedType(scope, aType, requireExactType);} else if (upperBound != null || lowerBound != null) {// this must be a generic wildcard with bounds// 泛型类型存在边界ret = resolveGenericWildcard(scope, aType);} else {// String... 可变参数,dim 不为 0if (dim != 0) {aType = UnresolvedType.makeArray(aType, dim);  // 数组类型 java.lang.String[]}ret = new ExactTypePattern(aType, includeSubtypes, isVarArgs);}ret.setAnnotationTypePattern(annotationPattern);ret.copyLocationFrom(this);return ret;
}

此处根据不同的条件,执行不同的封装策略。如果存在泛型参数,执行 WildTypePattern#resolveParameterizedType,将 WildTypePattern 封装为 ExactTypePattern。

默认情况下,如果 dim 不为 0,即存在数组类型或可变参数,将其统一处理为数组类型对应的字节码签名

public static UnresolvedType makeArray(UnresolvedType base, int dims) {StringBuffer sig = new StringBuffer();for (int i = 0; i < dims; i++) {sig.append("[");}sig.append(base.getSignature());  // "[Ljava/lang/String;"return UnresolvedType.forSignature(sig.toString());
}

 例如,base 为 "java.lang.String",处理后,signature 变为 "[Ljava/lang/String",接着利用 TypeFactory#createTypeFromSignature 为 signature 创建 UnresolvedType。

// TypeFactory#createTypeFromSignature
...
} else if (firstChar == '[') {int dims = 0;while (signature.charAt(dims) == '[') {dims++;}// 数组元素类型UnresolvedType componentType = createTypeFromSignature(signature.substring(dims));return new UnresolvedType(signature, signature.substring(0, dims) + componentType.getErasureSignature());
}
...

针对签名字符串 "Ljava/lang/String;" 和 "[Ljava/lang/String;" 分别创建 UnresolvedType,之后将数组签名字符串创建的 UnresolvedType 返回,视为 aType。

之后,封装一个 ExactTypePattern。就这样,将一个 "String..." 解析为 java.lang.String[]。

顺便说下,由于在 scope.lookupType 中对 importedPrefixes 进行了扩充,也就是和切面类在同一个包下的类,配置为切入点表达式类型时,也可以简写为类名的形式,不用指定包名。

示例二

execution(* *..UserServiceImpl.doSome(java.util.List<String>,int))

参数解析

经过前面的介绍,我们知道,(java.util.List<String>,int) 会被解析成两个 TypePattern,之后封装成一个 TypePatternList。解析第一个参数类型时,由于存在泛型参数,会调用 PatternParser#maybeParseTypeParameterList。

// 泛型参数解析 "<,>"
public TypePatternList maybeParseTypeParameterList() {if (!maybeEat("<")) {return null;}List<TypePattern> typePats = new ArrayList<>();do {TypePattern tp = parseTypePattern(true, false);typePats.add(tp);} while (maybeEat(","));eat(">");TypePattern[] tps = new TypePattern[typePats.size()];typePats.toArray(tps);return new TypePatternList(tps);
}

可以看到,又转化为对单个类型的解析。之后将所有的泛型参数类型封装成一个 TypePatternList。

此处将 "java.util.List<String>" 封装为 WildTypePattern,持有字段 typeParameters 为 "String" 封装的 WildTypePattern 所组成的 TypePatternList。

类型绑定

直接来看参数绑定,在 WildTypePattern#resolveBindings 中,针对 "java.util.List<String>" 封装的 WildTypePattern,由于 typeParameters 不为 null。执行 typeParameters.resolveBindings(...),即执行 TypeParameterList#resolveBindings。遍历每一个泛型类型,执行 WildTypePattern#resolveBindings。也就是说,只要是类型,最终都会转换到 WildTypePattern#resolveBindings 来执行。

将 "String" 封装的 WildTypePattern,在 WildTypePattern#resolveBindingsFromFullyQualifiedTypeName 中添加默认前缀,处理为 "java.lang.String",之后封装为 ExactTypePattern。

接着来看 "java.util.List" 的绑定,在 WildTypePattern#resolveBindings 中,得到fullyQualifiedName 为 "java.util.List",接着执行 WildTypePattern#resolveBindingsFromFullyQualifiedTypeName --> lookupTypeInWorldIncludingPrefixes  --> lookupTypeInWorld,先将 "java.util.List" 封装成 typeKind 为 TypeKind.SIMPLE 的 UnresolvedType,之后执行 World#resolve。在 typeMap 中未查找到,执行 World#resolveToReferenceType。封装 simpleOrRawType,之后为其创建 delegate。利用 classLoader 加载 "java.util.List" 得到 aClass,在 Java15ReflectionBasedReferenceTypeDelegate#initialize 方法中将 aClass 传递给 Java15ReflectionBasedReferenceTypeDelegate 父类 ReflectionBasedReferenceTypeDelegate 中 myClass 字段。

创建完 delegate,在 World#resolveToReference 中,调用 delegate.isGeneric()。

@Override
public boolean isGeneric() {// return false; // for nowreturn getBaseClass().getTypeParameters().length > 0;
}
protected Class getBaseClass() {return this.myClass;
}

java.util.List 定义时就存在泛型参数,所以此时返回 true。将 simpleOrRawType 中 typeKind 修改为 TypeKind.RAW,接着执行 World#makeGenericTypeFrom。

// World
private ReferenceType makeGenericTypeFrom(ReferenceTypeDelegate delegate, ReferenceType rawType) {String genericSig = delegate.getDeclaredGenericSignature();if (genericSig != null) {return new ReferenceType(UnresolvedType.forGenericTypeSignature(rawType.getSignature(),delegate.getDeclaredGenericSignature()), this);} else {// 执行 elsereturn new ReferenceType(UnresolvedType.forGenericTypeVariables(rawType.getSignature(), delegate.getTypeVariables()),this);}
}// Java15ReflectionBasedReferenceTypeDelegate
@Override
public TypeVariable[] getTypeVariables() {// nullTypeVariable[] workInProgressSetOfVariables = getResolvedTypeX().getWorld().getTypeVariablesCurrentlyBeingProcessed(getBaseClass());if (workInProgressSetOfVariables != null) {return workInProgressSetOfVariables;}if (this.typeVariables == null) {java.lang.reflect.TypeVariable[] tVars = this.getBaseClass().getTypeParameters();// org.aspectj.weaver.TypeVariableTypeVariable[] rTypeVariables = new TypeVariable[tVars.length];// basic initializationfor (int i = 0; i < tVars.length; i++) {rTypeVariables[i] = new TypeVariable(tVars[i].getName());}// stash itthis.getResolvedTypeX().getWorld().recordTypeVariablesCurrentlyBeingProcessed(getBaseClass(), rTypeVariables);// now fill in the details...for (int i = 0; i < tVars.length; i++) {// 处理 java.lang.reflect.TypeVariable,将其处理成 TypeVariableReferenceTypeTypeVariableReferenceType tvrt = ((TypeVariableReferenceType) typeConverter.fromType(tVars[i]));TypeVariable tv = tvrt.getTypeVariable();rTypeVariables[i].setSuperclass(tv.getSuperclass());rTypeVariables[i].setAdditionalInterfaceBounds(tv.getSuperInterfaces());rTypeVariables[i].setDeclaringElement(tv.getDeclaringElement());rTypeVariables[i].setDeclaringElementKind(tv.getDeclaringElementKind());rTypeVariables[i].setRank(tv.getRank());}this.typeVariables = rTypeVariables;this.getResolvedTypeX().getWorld().forgetTypeVariablesCurrentlyBeingProcessed(getBaseClass());}return this.typeVariables;
}// JavaLangTypeToResolvedTypeConverter
public ResolvedType fromType(Type type) {if (type instanceof Class) {Class clazz = (Class) type;String name = clazz.getName();/*** getName() can return:** 1. If this class object represents a reference type that is not an* array type then the binary name of the class is returned* 2. If this class object represents a primitive type or void, then* the name returned is a String equal to the Java language keyword* corresponding to the primitive type or void.* 3. If this class object represents a class of arrays, then the internal* form of the name consists of the name of the element type preceded by* one or more '[' characters representing the depth of the array nesting.*/if (clazz.isArray()) {UnresolvedType ut = UnresolvedType.forSignature(name.replace('.', '/'));return getWorld().resolve(ut);} else {return getWorld().resolve(name);}} else if (type instanceof ParameterizedType) {// https://bugs.eclipse.org/bugs/show_bug.cgi?id=509327// TODO should deal with the ownerType if it set, indicating this is possibly an inner type of a parameterized typeType ownerType = ((ParameterizedType) type).getOwnerType();ParameterizedType parameterizedType = (ParameterizedType) type;ResolvedType baseType = fromType(parameterizedType.getRawType());Type[] typeArguments = parameterizedType.getActualTypeArguments();if (baseType.isSimpleType() && typeArguments.length == 0 && ownerType != null) {// 'type' is an inner type of some outer parameterized type// For now just return the base type - in future create the parameterized form of the outer// and use it with the inner. We return the base type to be compatible with what the// code does that accesses the info from the bytecode (unlike this code which accesses it// reflectively).return baseType;}ResolvedType[] resolvedTypeArguments = fromTypes(typeArguments);return TypeFactory.createParameterizedType(baseType, resolvedTypeArguments, getWorld());} else if (type instanceof java.lang.reflect.TypeVariable) {TypeVariableReferenceType inprogressVar = typeVariablesInProgress.get(type);if (inprogressVar != null) {return inprogressVar;}java.lang.reflect.TypeVariable tv = (java.lang.reflect.TypeVariable) type;// org.aspectj.weaver.TypeVariableTypeVariable rt_tv = new TypeVariable(tv.getName());// 将 rt_tv 封装为 TypeVariableReferenceTypeTypeVariableReferenceType tvrt = new TypeVariableReferenceType(rt_tv, getWorld());typeVariablesInProgress.put(type, tvrt); // record what we are working on, for recursion case// 处理边界Type[] bounds = tv.getBounds();ResolvedType[] resBounds = fromTypes(bounds);ResolvedType upperBound = resBounds[0];ResolvedType[] additionalBounds = new ResolvedType[0];if (resBounds.length > 1) {additionalBounds = new ResolvedType[resBounds.length - 1];System.arraycopy(resBounds, 1, additionalBounds, 0, additionalBounds.length);}rt_tv.setUpperBound(upperBound);rt_tv.setAdditionalInterfaceBounds(additionalBounds);typeVariablesInProgress.remove(type); // we have finished working on itreturn tvrt;} else if (type instanceof WildcardType) {WildcardType wildType = (WildcardType) type;Type[] lowerBounds = wildType.getLowerBounds();Type[] upperBounds = wildType.getUpperBounds();ResolvedType bound = null;boolean isExtends = lowerBounds.length == 0;if (isExtends) {bound = fromType(upperBounds[0]);} else {bound = fromType(lowerBounds[0]);}return new BoundedReferenceType((ReferenceType) bound, isExtends, getWorld());} else if (type instanceof GenericArrayType) {GenericArrayType genericArrayType = (GenericArrayType) type;Type componentType = genericArrayType.getGenericComponentType();return UnresolvedType.makeArray(fromType(componentType), 1).resolve(getWorld());}return ResolvedType.MISSING;
}public TypeVariableReferenceType(TypeVariable typeVariable, World world) {super(typeVariable.getGenericSignature(), typeVariable.getErasureSignature(), world);this.typeVariable = typeVariable;
}
public String getGenericSignature() {return "T" + name + ";";
}
public String getErasureSignature() {return getFirstBound().getErasureSignature();
}// org.aspectj.weaver.TypeVariable
// 未指定返回 UnresolvedType.OBJECT
public UnresolvedType getFirstBound() {if (firstbound != null) {return firstbound;}if (superclass == null || superclass.getSignature().equals("Ljava/lang/Object;")) {if (superInterfaces.length > 0) {firstbound = superInterfaces[0];} else {firstbound = UnresolvedType.OBJECT;}} else {firstbound = superclass;}return firstbound;
}public static UnresolvedType forGenericTypeVariables(String sig, TypeVariable[] tVars) {UnresolvedType ret = UnresolvedType.forSignature(sig);ret.typeKind = TypeKind.GENERIC;ret.typeVariables = tVars;ret.signatureErasure = sig;ret.signature = ret.signatureErasure;return ret;
}public ReferenceType(UnresolvedType genericType, World world) {super(genericType.getSignature(), world);typeKind = TypeKind.GENERIC;this.typeVariables = genericType.typeVariables;
}

由于解析切入点表达式时,将一个类型中的类型和泛型分开解析,所以此处 this.getBaseClass().getTypeParameters() 相当于泛型擦除之后获取定义时的泛型变量,即 java.lang.reflect.TypeVariable。之后将 java.lang.reflect.TypeVariable 转换为 org.aspectj.weaver.TypeVariable。可以看到,对泛型类型变量的处理都是委托给 delegate 来处理的。

接着调用 UnresolvedType#forGenericTypeVariables,封装一个 typeKind 为 TypeKind.GENERIC 的 UnresolvedType,之后又依赖这个 UnresolvedType 封装一个 ReferenceType,作为 genericType,simpleOrRawType 和 genericType 共用一个 delegate,调用 ReferenceType#setGenericType,为 simpleOrRawType 中 genericType 属性赋值。最后将这个 simpleOrRawType 返回并缓存在 typeMap 中。

接着在 WildTypePattern#resolveBindingsFromFullyQualifiedTypeName 中调用 lookupTypeInScope,由于 "Ljava/util/List;" 已经缓存在了 typeMap 中,所以这一次直接从缓存获取。

完成这些准备工作之后,调用 WildTypePattern#resolveBindingsForExactType,此时由于存在 typeParameters,调用 WildTypePattern#resolveParameterizedType。

// WildTypePattern
private TypePattern resolveParameterizedType(IScope scope, UnresolvedType aType, boolean requireExactType) {// 保证 aType 已经解析ResolvedType rt = aType.resolve(scope.getWorld());if (!verifyTypeParameters(rt, scope, requireExactType)) {return TypePattern.NO; // messages already isued}// Only if the type is exact *and* the type parameters are exact should we create an// ExactTypePattern for this WildTypePattern// 实际泛型参数类型都已确定,且是否不允许子类型if (typeParameters.areAllExactWithNoSubtypesAllowed()) {TypePattern[] typePats = typeParameters.getTypePatterns();UnresolvedType[] typeParameterTypes = new UnresolvedType[typePats.length];for (int i = 0; i < typeParameterTypes.length; i++) {typeParameterTypes[i] = ((ExactTypePattern) typePats[i]).getExactType();}// rt could be a parameterized type 156058if (rt.isParameterizedType()) {rt = rt.getGenericType();}// 拼接 ParameterizedType,并完成 resolveResolvedType type = TypeFactory.createParameterizedType(rt, typeParameterTypes, scope.getWorld());if (isGeneric) {type = type.getGenericType();}// UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes);// UnresolvedType type = scope.getWorld().resolve(tx,true);if (dim != 0) {type = ResolvedType.makeArray(type, dim);}return new ExactTypePattern(type, includeSubtypes, isVarArgs);} else {// AMC... just leave it as a wild type pattern then?importedPrefixes = scope.getImportedPrefixes();knownMatches = preMatch(scope.getImportedNames());return this;}
}
// TypeFactory
public static ReferenceType createParameterizedType(ResolvedType aBaseType, UnresolvedType[] someTypeParameters, World inAWorld) {ResolvedType baseType = aBaseType;if (!aBaseType.isGenericType()) {if (someTypeParameters != null && someTypeParameters.length > 0) {if (!aBaseType.isRawType()) {throw new IllegalStateException("Expecting raw type, but " + aBaseType+" is of type "+aBaseType.getTypekind());}// 获取 genericType 作为 baseTypebaseType = baseType.getGenericType();if (baseType == null) {throw new IllegalStateException("Raw type does not have generic type set");}} // else if someTypeParameters is null, then the base type is allowed to be non-generic, it's an inner}ResolvedType[] resolvedParameters = inAWorld.resolve(someTypeParameters);// 是否已经存在衍生品ReferenceType existingType = ((ReferenceType)baseType).findDerivativeType(resolvedParameters);ReferenceType pType = null;if (existingType!=null) {pType = existingType;} else {// 创建衍生品pType =new ReferenceType(baseType, resolvedParameters, inAWorld);}// 放入 typeMapreturn (ReferenceType) pType.resolve(inAWorld);
}public ReferenceType(ResolvedType theGenericType,ResolvedType[] theParameters, World aWorld) {// 拼接的参数化签名为:"Pjava/util/List<Ljava/lang/String;>;"// 泛型擦除后的签名:"Ljava/util/List;"super(makeParameterizedSignature(theGenericType, theParameters),theGenericType.signatureErasure, aWorld);ReferenceType genericReferenceType = (ReferenceType) theGenericType;this.typeParameters = theParameters;this.genericType = genericReferenceType;this.typeKind = TypeKind.PARAMETERIZED;this.delegate = genericReferenceType.getDelegate();// 将拼接的衍生品作为泛型类型的依赖genericReferenceType.addDependentType(this);
}
// 拼接参数化签名
private static String makeParameterizedSignature(ResolvedType aGenericType,ResolvedType[] someParameters) {// Ljava/util/List;String rawSignature = aGenericType.getErasureSignature();StringBuffer ret = new StringBuffer();ret.append(PARAMETERIZED_TYPE_IDENTIFIER);ret.append(rawSignature.substring(1, rawSignature.length() - 1));ret.append("<");for (ResolvedType someParameter : someParameters) {ret.append(someParameter.getSignature());}ret.append(">;");return ret.toString();
}
synchronized void addDependentType(ReferenceType dependent) {// 添加依赖synchronized (derivativeTypes) {this.derivativeTypes.add(new WeakReference<>(dependent));}
}

从 aBaseType,也就是前面返回的 simpleOrRawType 中获取 genericType 作为 baseType,将类型和泛型实参类型拼接起来,作为 signature,之后封装 ReferenceType,此时 typeKind 为 TypeKind.PARAMETERIZED。

java.util.List<String> 被处理为 "Pjava/util/List<Ljava/lang/String;>;",称之为衍生品。

最后将这个衍生品 ReferenceType 传递给 ExactTypePattern。

这样就完成了泛型类型的类型绑定,解析的时候,将定义类型和泛型参数类型分开,统一封装到 WildTypePattern,之后在类型绑定时,将其具体类型和实际泛型参数类型拼接为一个字符串,封装 ReferenceType,传递给 ExactTypePattern

关键字:腾讯云域名查询_网页建设的公司_网络营销环境分析_杭州网站推广大全

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: