在 spring 中,对注解的操作,都位于 spring-core 模块下的 org.springframework.core.annotation 包中。通过 annotation 包中定义的相关类,完成对类型、方法、字段等元素上注解的操作。
主要类介绍
MergedAnnotations 接口,为 Spring 中公共组件模型中的组合注解而设计,重点是属性别名和 meta-annotation。通过定义一系列 static 类型的 from 方法来创建 TypeMappedAnnotations 对象,通过 of 方法来创建 MergedAnnotationsCollection 对象。
MergedAnnotationsCollection MergedAnnotation 集合对应的 MergedAnnotations 实现,通过 MergedAnnotations#of 调用 MergedAnnotationsCollection.of 进行创建,只在 classreading 包下进行字节码文件访问时 SimpleMethodMetadataReadingVisitor#visitEnd 和 SimpleAnnotationMetadataReadingVisitor#visitEnd 中使用。
TypeMappedAnnotations 通过两个 static 方法 TypeMappedAnnotations#from 进行 TypeMappedAnnotations 实例对象的创建,区别在于传参不同,一个针对 AnnotatedElement,另一个针对 Annotation[];定义了一系列 get 方法,获取 TypeMappedAnnotations 中指定 annotationType 对应的 TypeMappedAnnotation,当 TypeMappedAnnotations 中 Annotation[] 不为 null,则通过指定的 AnnotationProcessor 通过遍历 Annotation[],对指定的 Annotation,创建 AnnotationTypeMappings 映射,接着进行匹配,匹配到了,创建 TypeMappedAnnotation 对象返回,当 Annotation[] 为 null 时,委托给 AnnotationsScanner#scan 进行处理,先获取 AnnotatedElement 上持有的注解,接着就按 Annotation[] 不为 null 时进行处理。
MergedAnnotation 接口
AbstractMergedAnnotation 抽象实现
TypeMappedAnnotation MergedAnnotation 主要实现类,持有 AnnotationTypeMapping。
MissingMergedAnnotation 从 MergedAnnotations 中获取指定 annotationType 对应的MergedAnnotation 时,不存在,返回 MissingMergedAnnotation.getInstance()。
AnnotationTypeMappings 针对给定的 annotationType,构造 AnnotationTypeMapping 映射集合,会合并 meta-annotation,后续判断是否持有某个注解,也是通过对 AnnotationTypeMappings 的遍历来进行匹配。
AnnotationTypeMapping 一个 annotationType 对应一个 AnnotationTypeMapping。
AttributeMethods 对注解中定义属性方法的封装,通过 isAttributeMethod 来判断注解中某个方法是否是属性方法,即参数个数为0,返回类型不为 void。
@AliasFor 别名方法,只定义在方法上。例如定义在 @Service value 方法上,表示其是 @Component 中 value 方法的别称。
AnnotationScanner 注解扫描器,工具类,在给定 AnnotatedElement 注解的层次结构中搜索相关注解。
AnnotationUtils 定义了一系列 getAnnotation/findAnnotation 方法,通过 MergedAnnotations.from 创建 TypeMappedAnnotations 对象,接着调用 TypeMappedAnnotations#get 方法获取指定类型的 TypeMappedAnnotation,最后调用 AbstractMergedAnnotation#synthesize 创建 Annotation 对象。
AnnotatedElementUtils 工具类,为 spring 中 meta-annotation 编程模型定义的公共 API。常用 hasAnnotation 方法判断给定 AnnotatedElement 上是否持有某个类型的注解。
AnnotationFilter 注解过滤器,常用 PackagesAnnotationFilter,即根据指定的包过滤注解。
RepeatableContainers 注解容器,两个子类,RepeatableContainers$StandardRepeatableContainers,RepeatableContainers$NoRepeatableContainers,前者相较于后者增加了缓存的功能。
AnnotationsProcessor 处理注解的回调接口,常用实现类 TypeMappedAnnotations$MergedAnnotationFinder。
MergedAnnotationSelectors 选择 TypeMappedAnnotation 实例对象的策略接口,常用实现类 MergedAnnotationSelectors$Nearest。
下面通过一个应用,来看下 spring 中注解操作的逻辑实现。
包扫描模式下注解的应用
在基于注解的包扫描模式下,需要判断指定包下 class 文件是否持有指定的注解,此时通过 ClassReader 来读取字节码文件中类的相关信息,当类上持有注解时,通过 classVisitor.visitAnnotation 得到 MergedAnnotationReadingVisitor 对象来进行注解的访问,访问结束时,调用 annotationVisitor.visitEnd()。
// MergedAnnotationReadingVisitor
@Override
public void visitEnd() {MergedAnnotation<A> annotation = MergedAnnotation.of(this.classLoader, this.source, this.annotationType, this.attributes);this.consumer.accept(annotation);
}
static <A extends Annotation> MergedAnnotation<A> of(@Nullable ClassLoader classLoader, @Nullable Object source,Class<A> annotationType, @Nullable Map<String, ?> attributes) {return TypeMappedAnnotation.of(classLoader, source, annotationType, attributes);
}static <A extends Annotation> MergedAnnotation<A> of(@Nullable ClassLoader classLoader, @Nullable Object source,Class<A> annotationType, @Nullable Map<String, ?> attributes) {Assert.notNull(annotationType, "Annotation type must not be null");AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(annotationType);// 取 mappings 中第一个作为 TypeMappedAnnotation 中的 AnnotationTypeMappingreturn new TypeMappedAnnotation<>(mappings.get(0), classLoader, source, attributes, TypeMappedAnnotation::extractFromMap, 0);
}
首先,为指定的 annotationType 生成 AnnotationTypeMappings。
AnnotationTypeMappings 的创建
static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType) {return forAnnotationType(annotationType, new HashSet<>());
}
static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType,Set<Class<? extends Annotation>> visitedAnnotationTypes) {return forAnnotationType(annotationType, RepeatableContainers.standardRepeatables(),AnnotationFilter.PLAIN, visitedAnnotationTypes);
}
private static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType,RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter,Set<Class<? extends Annotation>> visitedAnnotationTypes) {if (repeatableContainers == RepeatableContainers.standardRepeatables()) {return standardRepeatablesCache.computeIfAbsent(annotationFilter,key -> new Cache(repeatableContainers, key)).get(annotationType, visitedAnnotationTypes);}if (repeatableContainers == RepeatableContainers.none()) {return noRepeatablesCache.computeIfAbsent(annotationFilter,key -> new Cache(repeatableContainers, key)).get(annotationType, visitedAnnotationTypes);}return new AnnotationTypeMappings(repeatableContainers, annotationFilter, annotationType, visitedAnnotationTypes);
}
在最后的执行方法中,用到了两个缓存,standardRepeatablesCache 和 noRepeatablesCache,这是 spring 中定义的 Map,ConcurrentReferenceHashMap,key 为 AnnotationFilter,value 为 Cache,这是 AnnotationTypeMappings 中的内部类。也就是说,一个 AnnotationFilter 对应一个 Cache。接着来看看这个 Cache 到底是什么。
// AnnotationTypeMappings$Cache
Cache(RepeatableContainers repeatableContainers, AnnotationFilter filter) {this.repeatableContainers = repeatableContainers;this.filter = filter;this.mappings = new ConcurrentReferenceHashMap<>();
}
这个 Cache 中的 mappings 才是真正的缓存对象,key 为注解类型对应的 Class 对象,value 为 AnnotationTypeMappings。
不管是 standardRepeatablesCache,还是 noRepeatablesCache,获取到 Cache 对象后,调用其 get 方法。
AnnotationTypeMappings get(Class<? extends Annotation> annotationType,Set<Class<? extends Annotation>> visitedAnnotationTypes) {return this.mappings.computeIfAbsent(annotationType, key -> createMappings(key, visitedAnnotationTypes));
}private AnnotationTypeMappings createMappings(Class<? extends Annotation> annotationType,Set<Class<? extends Annotation>> visitedAnnotationTypes) {return new AnnotationTypeMappings(this.repeatableContainers, this.filter, annotationType, visitedAnnotationTypes);
}
mappings 缓存中不存在 annotationType 对应的 key,调用 createMappings 进行创建。
private AnnotationTypeMappings(RepeatableContainers repeatableContainers,AnnotationFilter filter, Class<? extends Annotation> annotationType,Set<Class<? extends Annotation>> visitedAnnotationTypes) {this.repeatableContainers = repeatableContainers;this.filter = filter;this.mappings = new ArrayList<>();// 创建 AnnotationTypeMapping,添加进 mappingsaddAllMappings(annotationType, visitedAnnotationTypes);// 校验,清空 AnnotationTypeMapping.claimedAliasesthis.mappings.forEach(AnnotationTypeMapping::afterAllMappingsSet);
}
此处主要关注 addAllMappings 方法,就是在这一步生成了所有的映射。
private void addAllMappings(Class<? extends Annotation> annotationType,Set<Class<? extends Annotation>> visitedAnnotationTypes) {Deque<AnnotationTypeMapping> queue = new ArrayDeque<>();addIfPossible(queue, null, annotationType, null, visitedAnnotationTypes);while (!queue.isEmpty()) {AnnotationTypeMapping mapping = queue.removeFirst();this.mappings.add(mapping);// 添加 meta-annotation addMetaAnnotationsToQueue(queue, mapping);}
}
其实现逻辑:
- 将 annotationType 封装成 AnnotationTypeMapping,并将其加入队列
- 此时队列不为空,移除刚加入的 AnnotationTypeMapping,将其加入 AnnotationTypeMappings 中字段 mappings
- 以此 mapping 为基础,加入其上 meta-annotation 到队列中,然后进行下一次循环
此处处理类似于图的广度优先遍历,借助队列来实现。
private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable AnnotationTypeMapping source,Class<? extends Annotation> annotationType, @Nullable Annotation ann,Set<Class<? extends Annotation>> visitedAnnotationTypes) {try {queue.addLast(new AnnotationTypeMapping(source, annotationType, ann, visitedAnnotationTypes));}catch (Exception ex) {...}
}
下面来看看 annotationType 到底是如何封装成 AnnotationTypeMapping 的。
AnnotationTypeMapping 的创建
AnnotationTypeMapping(@Nullable AnnotationTypeMapping source, Class<? extends Annotation> annotationType,@Nullable Annotation annotation, Set<Class<? extends Annotation>> visitedAnnotationTypes) {this.source = source;this.root = (source != null ? source.getRoot() : this);this.distance = (source == null ? 0 : source.getDistance() + 1);this.annotationType = annotationType;this.metaTypes = merge(source != null ? source.getMetaTypes() : null,annotationType);this.annotation = annotation;this.attributes = AttributeMethods.forAnnotationType(annotationType);this.mirrorSets = new MirrorSets();this.aliasMappings = filledIntArray(this.attributes.size());this.conventionMappings = filledIntArray(this.attributes.size());this.annotationValueMappings = filledIntArray(this.attributes.size());this.annotationValueSource = new AnnotationTypeMapping[this.attributes.size()];// 解析 AttributeMethods 中每个 method 上的 @AliasFor 注解this.aliasedBy = resolveAliasedForTargets(); // 遍历 attributes 属性方法,判断当前某个 attribute 是否是其它注解的 别名方法processAliases(); addConventionMappings();addConventionAnnotationValues();this.synthesizable = computeSynthesizableFlag(visitedAnnotationTypes);
}
先来看 AttributeMethods 的创建。
AttributeMethods 的创建
static AttributeMethods forAnnotationType(@Nullable Class<? extends Annotation> annotationType) {if (annotationType == null) {return NONE;}// AttributeMethods 中 static 缓存,即同一个注解类型,整个系统中 compute 只执行一次return cache.computeIfAbsent(annotationType, AttributeMethods::compute);
}
此处也用到了缓存,key 为注解类型对应的 Class 对象,value 为 AttributeMethods,同一个系统中,针对同一个 annotationType,compute 方法只执行一次。
private static AttributeMethods compute(Class<? extends Annotation> annotationType) {// 获取注解中定义方法Method[] methods = annotationType.getDeclaredMethods();int size = methods.length;for (int i = 0; i < methods.length; i++) {// 非属性方法置为 nullif (!isAttributeMethod(methods[i])) {methods[i] = null;size--;}}if (size == 0) {return NONE;}// 排序Arrays.sort(methods, methodComparator);// 只复制 属性方法Method[] attributeMethods = Arrays.copyOf(methods, size);return new AttributeMethods(annotationType, attributeMethods);
}// 判断是否是属性方法
private static boolean isAttributeMethod(Method method) {return (method.getParameterCount() == 0 && method.getReturnType() != void.class);
}private AttributeMethods(@Nullable Class<? extends Annotation> annotationType, Method[] attributeMethods) {this.annotationType = annotationType;this.attributeMethods = attributeMethods;this.canThrowTypeNotPresentException = new boolean[attributeMethods.length];boolean foundDefaultValueMethod = false;boolean foundNestedAnnotation = false;for (int i = 0; i < attributeMethods.length; i++) {Method method = this.attributeMethods[i];// 返回值类型Class<?> type = method.getReturnType();if (!foundDefaultValueMethod && (method.getDefaultValue() != null)) {foundDefaultValueMethod = true;}if (!foundNestedAnnotation && (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation()))) {foundNestedAnnotation = true;}ReflectionUtils.makeAccessible(method);// 返回值为以下三种类型才可抛出异常this.canThrowTypeNotPresentException[i] = (type == Class.class || type == Class[].class || type.isEnum());}this.hasDefaultValueMethod = foundDefaultValueMethod;this.hasNestedAnnotation = foundNestedAnnotation;
}
这样就完成了 AttributeMethods 的创建。
接着在 resolveAliasedForTargets 中,遍历刚获得的 AttributeMethods 中的 attributeMethods,处理其上持有的 @AliasFor 注解。
private Map<Method, List<Method>> resolveAliasedForTargets() {Map<Method, List<Method>> aliasedBy = new HashMap<>();for (int i = 0; i < this.attributes.size(); i++) {Method attribute = this.attributes.get(i);// 获取 @AliasFor 实例对象AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, AliasFor.class);if (aliasFor != null) {Method target = resolveAliasTarget(attribute, aliasFor);// key 是 target 方法,value 是 attribute 方法aliasedBy.computeIfAbsent(target, key -> new ArrayList<>()).add(attribute);}}return Collections.unmodifiableMap(aliasedBy);
}
通过 AnnotationsScanner#getDeclaredAnnotation 来获取属性方法 attribute 上持有的 @AliasFor 注解对象。
// AnnotationScanner
@Nullable
static <A extends Annotation> A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {// 获取定义的注解,接着遍历,只要有一个与给定 annotationType 类型一致,就将这个 annotation 实例对象返回Annotation[] annotations = getDeclaredAnnotations(source, false);for (Annotation annotation : annotations) {if (annotation != null && annotationType == annotation.annotationType()) {return (A) annotation;}}return null;
}static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {boolean cached = false;// static 类型,先从缓存获取Annotation[] annotations = declaredAnnotationCache.get(source);if (annotations != null) {cached = true;}else {// 获取 source 上定义的 注解// source 为 @Service 中定义的属性方法时,此时调用 getDeclaredAnnotations 会获取到其方法上定义的注解对象annotations = source.getDeclaredAnnotations();if (annotations.length != 0) {boolean allIgnored = true;// 遍历for (int i = 0; i < annotations.length; i++) {Annotation annotation = annotations[i];// 判断注解对象中注解是否是可忽略的// 举例:针对 @Service,此时 annotation.annotationType() 为 @AliasFor// 调用 AttributeMethods.forAnnotationType 方法,针对 @AliasFor,属性方法有三个if (isIgnorable(annotation.annotationType()) ||!AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {annotations[i] = null;}else {allIgnored = false;}}annotations = (allIgnored ? NO_ANNOTATIONS : annotations);if (source instanceof Class || source instanceof Member) {// 放入缓存declaredAnnotationCache.put(source, annotations);cached = true;}}}if (!defensive || annotations.length == 0 || !cached) {return annotations;}return annotations.clone();
}private static boolean isIgnorable(Class<?> annotationType) {return AnnotationFilter.PLAIN.matches(annotationType);
}boolean isValid(Annotation annotation) {assertAnnotation(annotation);for (int i = 0; i < size(); i++) {if (canThrowTypeNotPresentException(i)) {try {get(i).invoke(annotation);}catch (Throwable ex) {return false;}}}return true;
}
在 AnnotationsScanner#getDeclaredAnnotations 获取 AnnotatedElement 上注解时也采用了缓存,获取时缓存不存在,才调用 java.lang.reflect.AnnotatedElement#getDeclaredAnnotations 去获取注解对象,之后进行过滤,不符合条件的一律置为 null,过滤条件有两个
- isIgnore,AnnotationFilter.PLAIN 包含的包名下的注解
- 给定注解类型下封装的 AttributeMethods 对于 给定注解 无效
此处第二个过滤条件,调用 AttributeMethods#forAnnotationType,@AliasFor 如果是第一次处理,会调用 compute 方法计算之后,将属性方法放入缓存。
处理完之后,将处理过的注解数组放入缓存。 所以当执行完 AnnotationsScanner#getDeclaredAnnotations 后,每个 source 对应的 annotations 和每个
annotation 对应的 AttributeMethods 都已确定。
获取到 @AliasFor 注解对象之后,调用 resolveAliasTarget,解析属性方法 attribute 上 @AliasFor 注解对应的目标方法。
// AnnotationTypeMapping
private Method resolveAliasTarget(Method attribute, AliasFor aliasFor) {return resolveAliasTarget(attribute, aliasFor, true);
}private Method resolveAliasTarget(Method attribute, AliasFor aliasFor, boolean checkAliasPair) {// @AliasFor 中 value 和 attribute 只能设置一个if (StringUtils.hasText(aliasFor.value()) && StringUtils.hasText(aliasFor.attribute())) {throw ...}// 获取注解类型Class<? extends Annotation> targetAnnotation = aliasFor.annotation();if (targetAnnotation == Annotation.class) {targetAnnotation = this.annotationType;}String targetAttributeName = aliasFor.attribute();if (!StringUtils.hasLength(targetAttributeName)) {targetAttributeName = aliasFor.value();}if (!StringUtils.hasLength(targetAttributeName)) {// @AliasFor value 和 attribute 都未配置,取当前 attribute 方法名称// "value"targetAttributeName = attribute.getName(); }// 获取目标注解中的目标属性// 此时 targetAnnotation,即 @ComponentMethod target = AttributeMethods.forAnnotationType(targetAnnotation).get(targetAttributeName);if (target == null) {if (targetAnnotation == this.annotationType) {throw ...}throw ...}if (target.equals(attribute)) {throw ...}// 返回值类型不相同if (!isCompatibleReturnType(attribute.getReturnType(), target.getReturnType())) {throw ...}if (isAliasPair(target) && checkAliasPair) {AliasFor targetAliasFor = target.getAnnotation(AliasFor.class);if (targetAliasFor != null) {Method mirror = resolveAliasTarget(target, targetAliasFor, false);if (!mirror.equals(attribute)) {throw ...}}}return target;
}
调用 aliasFor.annotation() 方法获取目标注解类 targetAnnotation,接着获取目标属性名,先 attribute(),不存在,再 value(),都未配置,则获取当前属性方法 attribute 的名称,作为目标方法名称。接着 AttributeMethods#forAnnotationType,传入 targetAnnotation,得到 AttributeMethods,接着传入 targetMethodName,得到 targetMethod。
举个例子:
@Service 注解,属性方法:
@AliasFor(annotation = Component.class)
String value() default "";
调用 aliasFor.annotation() 得到 Component.class,这便是目标注解,此处 @AliasFor 中未配置 attribute 和 value,所以拿此属性方法名 value 作为目标方法名,但是又不确定目标注解中是否有此 value 方法,所以调用 AttributeMethods.forAnnotationType(targetAnnotation).get(targetAttributeName),得到目标属性方法,然后进行判断。
获取到目标方法后,放入 aliasedBy,数据结构 Map<Method, List<Method>>,此处将 target 作为 key,原属性方法 attribute 加入 value 对应的 list 集合,之后将 aliasedBy 赋值给 AnnotationTypeMapping 中 aliasedBy 字段。
这样就完成了 annotationType 到 AnnotationTypeMapping 的转换,之后以此 AnnotationTypeMapping 为 source,执行 addMetaAnnotationsToQueue。
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source) {// 扫描 source 对应注解类型上定义的注解Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType(), false);for (Annotation metaAnnotation : metaAnnotations) {if (!isMappable(source, metaAnnotation)) {continue;}Annotation[] repeatedAnnotations = this.repeatableContainers.findRepeatedAnnotations(metaAnnotation);// 为 nullif (repeatedAnnotations != null) {for (Annotation repeatedAnnotation : repeatedAnnotations) {if (!isMappable(source, repeatedAnnotation)) {continue;}addIfPossible(queue, source, repeatedAnnotation);}}else {addIfPossible(queue, source, metaAnnotation);}}
}
此处又调用到了 AnnotationsScanner#getDeclaredAnnotations,由于前面只在创建 AnnotationTypeMapping 时处理了属性方法,此处当传入 Class 对象时,从缓存获取不到,调用 java.lang.reflect.AnnotatedElement#getDeclaredAnnotations 获取。
举个例子:若为 Service.class,此时获取到其上的四个注解对象,前三个通过 isIgnorable 处理为 null,最后一个为 @Component,通过 AttributeMethods#forAnnotationType 进行处理,前面处理 属性方法上 @AliasFor 时已经处理过 @Component,所以在 AttributeMethods 中会直接返回 @Component 中定义的属性方法,之后 isValid 判断。接着将 Service.class 及其上注解放入 AnnotationsScanner 中 declaredAnnotationCache 缓存。
获取注解 Class 对象上的注解数组后,即 metaAnnotations,对其进行遍历。调用 isMappable 进行判断。
private boolean isMappable(AnnotationTypeMapping source, @Nullable Annotation metaAnnotation) {return (metaAnnotation != null && !this.filter.matches(metaAnnotation) &&!AnnotationFilter.PLAIN.matches(source.getAnnotationType()) &&!isAlreadyMapped(source, metaAnnotation));
}
private boolean isAlreadyMapped(AnnotationTypeMapping source, Annotation metaAnnotation) {// @ComponentClass<? extends Annotation> annotationType = metaAnnotation.annotationType();AnnotationTypeMapping mapping = source;while (mapping != null) {if (mapping.getAnnotationType() == annotationType) {return true;}mapping = mapping.getSource();}return false;
}
还是以 @Service 为例,前三个注解都被处理成 null,只有第四个 @Component,此时执行 isAlreadyMapped,其实就是判断当前注解类型,是否已被处理成了 AnnotationTypeMapping。
接着执行 this.repeatableContainers.findRepeatedAnnotations,之前传入的 repeatableContainers 为 RepeatableContainers.standardRepeatables(),即 RepeatableContainers$StandardRepeatableContainers。
// RepeatableContainers$StandardRepeatableContainers
@Override
@Nullable
Annotation[] findRepeatedAnnotations(Annotation annotation) {Method method = getRepeatedAnnotationsMethod(annotation.annotationType());if (method != null) {return (Annotation[]) ReflectionUtils.invokeMethod(method, annotation);}// 不存在 method,让父类去查找return super.findRepeatedAnnotations(annotation);
}
@Nullable
private static Method getRepeatedAnnotationsMethod(Class<? extends Annotation> annotationType) {// 计算缓存起来Object result = cache.computeIfAbsent(annotationType,StandardRepeatableContainers::computeRepeatedAnnotationsMethod);return (result != NONE ? (Method) result : null);
}
private static Object computeRepeatedAnnotationsMethod(Class<? extends Annotation> annotationType) {AttributeMethods methods = AttributeMethods.forAnnotationType(annotationType);// 只有一个 value 属性方法if (methods.hasOnlyValueAttribute()) {Method method = methods.get(0);// 判断返回值类型,只有数组类型Class<?> returnType = method.getReturnType();if (returnType.isArray()) {// 注解类型数组,元素类型被 @Repeatable 修饰,此时才将 method 返回Class<?> componentType = returnType.getComponentType();if (Annotation.class.isAssignableFrom(componentType) &&componentType.isAnnotationPresent(Repeatable.class)) {return method;}}}return NONE;
}
StandardRepeatableContainers 缓存中获取不到,进行 computeRepeatedAnnotationsMethod,只有属性方法名为 value,且只有一个属性方法,返回值为注解类型数组,且注解类型被 @Repeatable 修饰,才将当前属性方法返回,否则一律返回 NONE。
由于返回的 repeatedAnnotations 为 null,所以执行 else 中方法。
// AnnotationTypeMappings
private void addIfPossible(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source, Annotation ann) {addIfPossible(queue, source, ann.annotationType(), ann, new HashSet<>());
}
// 此时将 @Service 作为 source,annotationType 为 @Component
private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable AnnotationTypeMapping source,Class<? extends Annotation> annotationType, @Nullable Annotation ann,Set<Class<? extends Annotation>> visitedAnnotationTypes) {try {queue.addLast(new AnnotationTypeMapping(source, annotationType, ann, visitedAnnotationTypes));}catch (Exception ex) {...}
}
还是以 @Service 举例,此时将 @Service 对应的 AnnotationTypeMapping 作为 source,将 meta-annotation 对应的 @Component,对其创建 AnnotationTypeMapping,并加入队列。
再次调用 AnnotationTypeMapping 构造方法,此时 source 为 @Service 对应的 AnnotationTypeMapping,root 为 @Service 对应的 AnnotationTypeMapping,distance 为 1,AttributeMethods 从缓存获取后直接赋值,resolveAliasedForTargets 时由于 @Component 中属性方法无 @AliasFor 注解,所以不做处理。接着 processAliases。
private void processAliases() {List<Method> aliases = new ArrayList<>();for (int i = 0; i < this.attributes.size(); i++) {aliases.clear();aliases.add(this.attributes.get(i));collectAliases(aliases);if (aliases.size() > 1) { // 存在别名,加入后 大于1processAliases(i, aliases);}}
}
private void collectAliases(List<Method> aliases) {AnnotationTypeMapping mapping = this;while (mapping != null) {int size = aliases.size();for (int j = 0; j < size; j++) {List<Method> additional = mapping.aliasedBy.get(aliases.get(j));if (additional != null) {aliases.addAll(additional);}}mapping = mapping.source; // 此时存在 source,进行下一次循环}
}
在 collectAliases 方法中,@Component 对应的 AnnotationTypeMapping 中是不含 @AliasFor 的,但其 source 对应的 AnnotationTypeMapping 含有,所以在进行第二次 while 循环时,拿出别名属性方法,加入 aliases 集合,之后执行含参的 processAliases。
private void processAliases(int attributeIndex, List<Method> aliases) {int rootAttributeIndex = getFirstRootAttributeIndex(aliases);AnnotationTypeMapping mapping = this;while (mapping != null) {if (rootAttributeIndex != -1 && mapping != this.root) {for (int i = 0; i < mapping.attributes.size(); i++) {if (aliases.contains(mapping.attributes.get(i))) {// 填充 aliasMappings,赋值mapping.aliasMappings[i] = rootAttributeIndex;}}}mapping.mirrorSets.updateFrom(aliases);mapping.claimedAliases.addAll(aliases);if (mapping.annotation != null) {int[] resolvedMirrors = mapping.mirrorSets.resolve(null,mapping.annotation, ReflectionUtils::invokeMethod);for (int i = 0; i < mapping.attributes.size(); i++) {if (aliases.contains(mapping.attributes.get(i))) {this.annotationValueMappings[attributeIndex] = resolvedMirrors[i];this.annotationValueSource[attributeIndex] = mapping;}}}mapping = mapping.source;}
}private int getFirstRootAttributeIndex(Collection<Method> aliases) {// @Component root 为 @ServiceAttributeMethods rootAttributes = this.root.getAttributes();for (int i = 0; i < rootAttributes.size(); i++) {// 集合含有,就将 i 返回if (aliases.contains(rootAttributes.get(i))) {return i;}}return -1;
}
此处只是为 AnnotationTypeMapping 构造方法中的一些字段进行填充。
之后,将 @Component 对应的 AnnotationTypeMapping 加入 AnnotationTypeMappings 中 mappings 集合。以此 @Component 对应的 AnnotationTypeMapping 为 source,再次调用 addMetaAnnotationsToQueue。
此时调用 AnnotationsScanner#getDeclaredAnnotations,传入 @Component 对应 Class,缓存不存在,调用 java.lang.reflect.AnnotatedElement#getDeclaredAnnotations,共 4 个注解,前三个处理为 null,第四个 @Indexed,接着加入缓存,key 为 @Component 对应 Class,value 为处理后的注解数组。并且前面对 @Indexed 进行判断时,将其加入了 AttributeMethods 中缓存。
接着调用 addIfPossible,创建 @Indexed 对应的 AnnotationTypeMapping。此时 source 为 @Component 对应的 AnnotationTypeMapping,root 为 @Service 对应的 AnnotationTypeMapping,distance 为 2,计算 synthesizable 标志为 false。之后将其加入 AnnotationTypeMappings 中 mappings 集合。
之后以 @Indexed 对应的 AnnotationTypeMapping 为 source,再次调用 addMetaAnnotationsToQueue。将 @Indexed 对应 Class 加入 AnnotationsScanner 中 declaredAnnotationCache 缓存。@Indexed 上注解都被处理为 null,当不存在 meta-annotation 处理,结束创建添加 AnnotationTypeMapping 的循环。
至此,AnnotationTypeMappings 创建结束,并将创建的 AnnotationTypeMappings 放入 AnnotationTypeMappings$Cache,key 为注解类型对应的 Class 对象,value 为 AnnotationTypeMappings。
接下来,取 AnnotationTypeMappings 中集合 mappings 中第一个 AnnotationTypeMapping,创建 TypeMappedAnnotation。
private TypeMappedAnnotation(AnnotationTypeMapping mapping, @Nullable ClassLoader classLoader,@Nullable Object source, @Nullable Object rootAttributes, ValueExtractor valueExtractor,int aggregateIndex, @Nullable int[] resolvedRootMirrors) {this.mapping = mapping;this.classLoader = classLoader;this.source = source;this.rootAttributes = rootAttributes;this.valueExtractor = valueExtractor;this.aggregateIndex = aggregateIndex;this.useMergedValues = true;this.attributeFilter = null;this.resolvedRootMirrors = (resolvedRootMirrors != null ? resolvedRootMirrors :mapping.getRoot().getMirrorSets().resolve(source, rootAttributes, this.valueExtractor));this.resolvedMirrors = (getDistance() == 0 ? this.resolvedRootMirrors :mapping.getMirrorSets().resolve(source, this, this::getValueForMirrorResolution));
}
在 MergedAnnotationReadingVisitor#visitEnd 中创建的 TypeMappedAnnotation 用来填充 SimpleAnnotationMetadataReadingVisitor 中 annotations 字段。当整个 class 文件访问结束时,调用 SimpleAnnotationMetadataReadingVisitor#visitEnd。
// SimpleAnnotationMetadataReadingVisitor
@Override
public void visitEnd() {String[] memberClassNames = StringUtils.toStringArray(this.memberClassNames);MethodMetadata[] annotatedMethods = this.annotatedMethods.toArray(new MethodMetadata[0]);MergedAnnotations annotations = MergedAnnotations.of(this.annotations);this.metadata = new SimpleAnnotationMetadata(this.className, this.access,this.enclosingClassName, this.superClassName, this.independentInnerClass,this.interfaceNames, memberClassNames, annotatedMethods, annotations);
}
此时,针对类上的注解集合,创建 MergedAnnotations,即 MergedAnnotationsCollection 对象。
MergedAnnotationsCollection 的创建
static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) {return MergedAnnotationsCollection.of(annotations);
}static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) {Assert.notNull(annotations, "Annotations must not be null");if (annotations.isEmpty()) {return TypeMappedAnnotations.NONE;}return new MergedAnnotationsCollection(annotations);
}private MergedAnnotationsCollection(Collection<MergedAnnotation<?>> annotations) {this.annotations = annotations.toArray(new MergedAnnotation<?>[0]);this.mappings = new AnnotationTypeMappings[this.annotations.length];for (int i = 0; i < this.annotations.length; i++) {MergedAnnotation<?> annotation = this.annotations[i];this.mappings[i] = AnnotationTypeMappings.forAnnotationType(annotation.getType());}
}
可以看到这是一个私有构造方法,只能通过这种方式创建 MergedAnnotationsCollection 对象。在构造方法中,主要是为其中 annotations 和 mappings 两个字段赋值。每一个 MergedAnnotation 对应一个 AnnotationTypeMappings,可以看到此处又调用了 AnnotationTypeMappings#forAnnotationType。此时,从 AnnotationTypeMappings 中对应的容器缓存,此处为 standardRepeatablesCache 中拿到 AnnotationTypeMappings$Cache,接着从 AnnotationTypeMappings$Cache 中 mappings 中拿到缓存的 AnnotationTypeMappings 进行赋值。
这样,就完成了 MergedAnnotationsCollection 对象的创建。
下面来看看创建的这些映射,是怎么使用的。
注解匹配
在基于注解的包扫描模式下,当通过 spring-core 模块下 classreading 包对封装的字节码 Resource 进行访问后,将访问到的信息封装成了 SimpleMetadataReader,之后对 SimpleMetadataReader 进行判断,是候选的组件,才进行 BeanDefinition 的创建。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;
}
通过 AbstractTypeHierarchyTraversingFilter#match 调用 AnnotationTypeFilter#matchSelf。
@Override
protected boolean matchSelf(MetadataReader metadataReader) {AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();return metadata.hasAnnotation(this.annotationType.getName()) ||(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}
先判断是否直接持有指定注解。
default boolean hasAnnotation(String annotationName) {return getAnnotations().isDirectlyPresent(annotationName);
}// SimpleAnnotationMetadata
@Override
public MergedAnnotations getAnnotations() {return this.annotations;
}
@Override
public boolean isDirectlyPresent(String annotationType) {return isPresent(annotationType, true);
}
private boolean isPresent(Object requiredType, boolean directOnly) {for (MergedAnnotation<?> annotation : this.annotations) {Class<? extends Annotation> type = annotation.getType();if (type == requiredType || type.getName().equals(requiredType)) {return true;}}// 为 true,不考虑 meta-annotationif (!directOnly) {for (AnnotationTypeMappings mappings : this.mappings) {for (int i = 1; i < mappings.size(); i++) {AnnotationTypeMapping mapping = mappings.get(i);if (isMappingForType(mapping, requiredType)) {return true;}}}}return false;
}
不存在,considerMetaAnnotations 为 true,判断 meta-annotation 是否持有指定注解。
// AnnotationMetadata
default boolean hasMetaAnnotation(String metaAnnotationName) {return getAnnotations().get(metaAnnotationName,MergedAnnotation::isMetaPresent).isPresent();
}
@Override
public MergedAnnotations getAnnotations() {return this.annotations;
}@Override
public <A extends Annotation> MergedAnnotation<A> get(String annotationType,@Nullable Predicate<? super MergedAnnotation<A>> predicate) {return get(annotationType, predicate, null);
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(String annotationType,@Nullable Predicate<? super MergedAnnotation<A>> predicate,@Nullable MergedAnnotationSelector<A> selector) {MergedAnnotation<A> result = find(annotationType, predicate, selector);return (result != null ? result : MergedAnnotation.missing());
}
@Nullable
private <A extends Annotation> MergedAnnotation<A> find(Object requiredType,@Nullable Predicate<? super MergedAnnotation<A>> predicate,@Nullable MergedAnnotationSelector<A> selector) {if (selector == null) {// 为 null,赋值selector = MergedAnnotationSelectors.nearest();}MergedAnnotation<A> result = null;for (int i = 0; i < this.annotations.length; i++) {MergedAnnotation<?> root = this.annotations[i];AnnotationTypeMappings mappings = this.mappings[i];for (int mappingIndex = 0; mappingIndex < mappings.size(); mappingIndex++) {AnnotationTypeMapping mapping = mappings.get(mappingIndex);if (!isMappingForType(mapping, requiredType)) {continue;}MergedAnnotation<A> candidate = (mappingIndex == 0 ? (MergedAnnotation<A>) root :TypeMappedAnnotation.createIfPossible(mapping, root, IntrospectionFailureLogger.INFO));if (candidate != null && (predicate == null || predicate.test(candidate))) {if (selector.isBestCandidate(candidate)) {return candidate;}result = (result != null ? selector.select(result, candidate) : candidate);}}}return result;
}private static boolean isMappingForType(AnnotationTypeMapping mapping, @Nullable Object requiredType) {if (requiredType == null) {return true;}Class<? extends Annotation> actualType = mapping.getAnnotationType();return (actualType == requiredType || actualType.getName().equals(requiredType));
}@Nullable
static <A extends Annotation> TypeMappedAnnotation<A> createIfPossible(AnnotationTypeMapping mapping, MergedAnnotation<?> annotation, IntrospectionFailureLogger logger) {if (annotation instanceof TypeMappedAnnotation) {TypeMappedAnnotation<?> typeMappedAnnotation = (TypeMappedAnnotation<?>) annotation;return createIfPossible(mapping, typeMappedAnnotation.source,typeMappedAnnotation.rootAttributes,typeMappedAnnotation.valueExtractor,typeMappedAnnotation.aggregateIndex, logger);}return createIfPossible(mapping, annotation.getSource(), annotation.synthesize(),annotation.getAggregateIndex(), logger);
}@Nullable
private static <A extends Annotation> TypeMappedAnnotation<A> createIfPossible(AnnotationTypeMapping mapping, @Nullable Object source, @Nullable Object rootAttribute,ValueExtractor valueExtractor, int aggregateIndex, IntrospectionFailureLogger logger) {try {return new TypeMappedAnnotation<>(mapping, null, source, rootAttribute,valueExtractor, aggregateIndex);}catch (Exception ex) {...return null;}
}// AbstractMergedAnnotation
@Override
public boolean isMetaPresent() {return isPresent() && getDistance() > 0;
}// MergedAnnotationSelectors$Nearest
@Override
public boolean isBestCandidate(MergedAnnotation<Annotation> annotation) {return annotation.getDistance() == 0;
}
核心方法就是 MergedAnnotationsCollection#find,首先,选择器不存在,定义一个选择器,用来挑选候选者。接着可以看到,对 MergedAnnotationsCollection 中 annotations 和 mappings 同时进行遍历,annotations 控制外部循环,因为一个 TypeMappedAnnotation 对应一个 AnnotationTypeMappings,对于内部循环,拿遍历到的 mapping,调用 isMappingForType 进行匹配,匹配到了,判断 mappingIndex 是否为 0,为 0,直接将外部循环下的 root 返回,因为之前创建 TypeMappedAnnotation 时,只对 AnnotationTypeMappings 中第一个 AnnotationTypeMapping 创建了 TypeMappedAnnotation。否则调用 TypeMappedAnnotation#createIfPossible 新建一个 TypeMappedAnnotation,作为 candidate,之后利用传入的条件 AbstractMergedAnnotation#isMetaPresent 进行判断,从 meta-annotation 中检索,TypeMappedAnnotation 中持有的 AnnotationTypeMapping 对应的 distance 应大于 0,之后再应用 selector 进行判断,distance 为 0,视为最优候选者,直接返回,否则为 result 赋值,进行下一次循环。
//MergedAnnotationSelectors$Nearest
@Override
public MergedAnnotation<Annotation> select(MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) {if (candidate.getDistance() < existing.getDistance()) {return candidate;}return existing;
}
如果再次循环又匹配到了,此时存在多个候选者,应用 selector 进行选择,针对 MergedAnnotationSelectors$Nearest 选择器,就是挑选 distance 最小的,赋值给 result,进行下一次循环。
最后内外循环结束,将 result 返回,不为 null,就是 TypeMappedAnnotation 对象,否则返回一个 MergedAnnotation.missing(),是一个 MissingMergedAnnotation 对象。
之后调用 MergedAnnotation#isPresent,对于 TypeMappedAnnotation 恒为 true,对于 MissingMergedAnnotation 恒为 false,也就是说,一旦返回了 TypeMappedAnnotation,那么肯定是存在指定注解的。
再比如前面 isCandidateComponent 中调用的 isConditionMatch,仍然是采用了注解匹配。
在 ConditionEvaluator#shouldSkip 中,执行了 metadata.isAnnotated(Conditional.class.getName()),判断 metadata 中是否持有 @Conditional 注解。
// AnnotatedTypeMetadata
default boolean isAnnotated(String annotationName) {return getAnnotations().isPresent(annotationName);
}// MergedAnnotationsCollection
@Override
public boolean isPresent(String annotationType) {return isPresent(annotationType, false);
}
private boolean isPresent(Object requiredType, boolean directOnly) {for (MergedAnnotation<?> annotation : this.annotations) {Class<? extends Annotation> type = annotation.getType();if (type == requiredType || type.getName().equals(requiredType)) {return true;}}if (!directOnly) {for (AnnotationTypeMappings mappings : this.mappings) {for (int i = 1; i < mappings.size(); i++) {AnnotationTypeMapping mapping = mappings.get(i);if (isMappingForType(mapping, requiredType)) {return true;}}}}return false;
}
directOnly 为 false,会去检索 meta-annotation,由于前面已经遍历了 annotations,每个 TypeMappedAnnotation 持有 AnnotationTypeMappings 中第一个 AnnotationTypeMapping,所以底下的 AnnotationTypeMappings 中 mappings 的遍历每次从索引 1 开始。
总结
一个 annotationType 对应一个 AnnotationTypeMapping,一个 TypeMappedAnnotation 持有一个 AnnotationTypeMapping;一个 annotationType 对应一个 AnnotationTypeMappings,此时会合并 meta-annotation,多个 TypeMappedAnnotation 对应一个 MergedAnnotations。
映射关系创建完成后,判断是否持有某个注解,就是对 AnnotationTypeMappings 中的 mappings 进行遍历,判断每一个 AnnotationTypeMapping 所对应的注解类型是否与指定注解类型一致。