本篇记录注解类型映射的实现,如下图圈出的部分:
注解类型映射的实现
注解过滤器定义 - AnnotationFilter
代码实现:
package cn.zhanghongyang.core.annotation;
import java.lang.annotation.Annotation;
/**
* @Author: zhanghongyang
* @Description: 注解过滤器
*/
public interface AnnotationFilter {
/**
* 声明过滤器,包含两个包
*/
AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
/**
* 生成过滤器
* @param pagckages 包名
* @return
*/
static AnnotationFilter packages(String... pagckages){
return new PackageAnnotationFilter(pagckages);
}
/**
* 匹配验证
* @param typeName 类型名称
* @return
*/
boolean matches(String typeName);
/**
* 匹配验证
* @param type 类型
* @return
*/
default boolean matches(Class<?> type){
return matches(type.getName());
}
/**
* 匹配验证
* @param annotation 注解
* @return
*/
default boolean matches(Annotation annotation){
return matches(annotation.annotationType());
}
}
注解过滤器的实现类(包注解过滤器) - PackageAnnotationFilter
主要根据注解的包进行过滤
功能演示:
//构建org.springframework.lang包的过滤器
AnnotationFilter annotationFilter = new PackagesAnnotationFilter("org.springframework.lang");
//匹配验证
boolean matches = annotationFilter.matches("org.springframework.lang.Nullable");
Assert.isTrue(matches);
代码实现:
package cn.zhanghongyang.core.annotation;
import java.util.Arrays;
/**
* @Author: zhanghongyang
* @Description: 包注解过滤器
*/
public class PackageAnnotationFilter implements AnnotationFilter{
//过滤包名的前缀
private String[] prefixes;
public PackageAnnotationFilter(String... packages) {
prefixes = new String[packages.length];
for (int i = 0; i < packages.length; i++) {
prefixes[i] = packages[i] + ".";
}
Arrays.sort(prefixes);
}
@Override
public boolean matches(String typeName) {
for (String prefix : prefixes) {
if (typeName.startsWith(prefix)){
return true;
}
}
return false;
}
}
注解扫描器 - AnnotationsScanner
功能演示:
功能介绍篇的案例@Zhy上打了@Zhy2注解,测试类打了@Zhy注解,测试案例代码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Zhy2
public @interface Zhy {
@AliasFor(value = "name")
String value() default "";
String name() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Zhy2 {
}
@Zhy(name = "张红洋")
public class ZhyTest {
public static void main(String[] args) {
Zhy annotation = ZhyTest.class.getAnnotation(Zhy.class);
Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(annotation.annotationType(), false);
System.out.println(metaAnnotations);
}
}
代码实现:
package cn.zhanghongyang.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: zhanghongyang
* @Date: 2021/8/12 14:02
* @Description: 注解扫描器
*/
public abstract class AnnotationsScanner {
private static final Map<AnnotatedElement, Annotation[]> declaredAnnotationCache = new ConcurrentHashMap<>(16);
/**
* 获取source的过滤后的注解,并缓存到内部
* @param source 需要扫描的元素(可以打注解的元素)
* @return source 过滤后的注解
*/
static Annotation[] getDeclaredAnnotations(AnnotatedElement source){
//从缓存中获取
Annotation[] annotations = declaredAnnotationCache.get(source);
if (annotations == null){
//获取到注解
annotations = source.getDeclaredAnnotations();
for (int i = 0; i < annotations.length; i++) {
//过滤判断,可以过滤掉Target等元注解
if (isIgnorable(annotations[i].annotationType())){
//如果是被忽略的赋值为null
annotations[i] = null;
}
}
//存入缓存
declaredAnnotationCache.put(source, annotations);
}
//返回的时候需要复制一份,防止缓存中的数据被修改
return annotations.clone();
}
private static boolean isIgnorable(Class<?> annotationType) {
//使用过滤器过滤
return AnnotationFilter.PLAIN.matches(annotationType);
}
}
注解类型的映射类 - AnnotationTypeMapping
主要作用保存注解的上下级关系,处理别名的映射关系
代码实现:
package cn.zhanghongyang.core.annotation;
import java.lang.annotation.Annotation;
/**
* @Author: zhanghongyang
* @Description: 注解类型的映射,这里忽略了别名的处理
*/
public class AnnotationTypeMapping {
//来源
private AnnotationTypeMapping source;
//注解是根(最开始的注解)
private AnnotationTypeMapping root;
//元注解类型
private Class<? extends Annotation> annotationType;
//元注解
private Annotation annotation;
//距离
private int distance;
public AnnotationTypeMapping(AnnotationTypeMapping source, Class<? extends Annotation> annotationType, Annotation annotation) {
this.source = source;
this.annotationType = annotationType;
this.annotation = annotation;
//如果没有来源,则距离是0,否则+1
this.distance = source == null ? 0 : source.getDistance() + 1;
//如果来源不是空,则获取来源的源,否则就是自己,这里的值是最开始的那个注解
this.root = source != null ? source.getSource(): this;
}
public AnnotationTypeMapping getSource() {
return source;
}
public AnnotationTypeMapping getRoot() {
return root;
}
public Class<? extends Annotation> getAnnotationType() {
return annotationType;
}
public Annotation getAnnotation() {
return annotation;
}
public int getDistance() {
return distance;
}
}
注解类型映射关系的集合 - AnnotationTypeMappings
获取注解的注解,注解的注解的注解…,每个注解使用AnnotationTypeMeppings保存。内部使用了两个缓存,一个缓存过滤器和注解映射集合的关系,一个缓存注解类型和注解映射集合的关系。
功能演示:
实例同上,@Zhy上打了@Zhy2,@Zhy2上打了@Zhy3。距离表示距离source的距离
代码实现
package cn.zhanghongyang.core.annotation;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: zhanghongyang
* @Description:
* 1 添加过滤器
* 2 获取获取器的Cache,没有则创建Cache
* 2.1 从Cache中获取注解对应的 AnnotationTypeMappings,AnnotationTypeMappings中存储了注解的元注解信息,如果不存在则创建
* 2.1.1 创建AnnotationTypeMappings,广度优先遍历获取元注解
* 2.1.1.1 使用AnnotationsScanner获取注解的所有元注解,并使用 AnnotationFilter.PLAIN 过滤符合条件的注解,不符合的置为null,并且缓存起来
* 2.1.2 再次使用步骤1添加的过滤器和其他条件过滤,符合添加的加入到队列中
*/
public class AnnotationTypeMappings {
/** Spring中使用了自定义的ConcurrentReferenceHashMap,是可以指定引用基本的ConcurrentHashMap,默认级别是软引用,在内存不足时会被回收,适合做缓存 */
private static final Map<AnnotationFilter, Cache> standardRepeatablesCache = new ConcurrentHashMap<>();
static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType){
//增加过滤器
return forAnnotationType(annotationType, AnnotationFilter.PLAIN);
}
static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType, AnnotationFilter annotationFilter){
// 将过滤器传递给Cache,Cache没有使用会再传递给AnnotationTypeMappings,
// 最终给还是在AnnotationTypeMappings中筛选注解使用,最终效果是从静态->非静态传递的过程
return standardRepeatablesCache.computeIfAbsent(annotationFilter, key -> new Cache(annotationFilter)).get(annotationType);
}
/**********************上面的静态变量和方法是缓存注解过滤器和Cache对应关系,只有一份***********************/
//保存注解的元注解,会封装成AnnotationTypeMapping类型
private final List<AnnotationTypeMapping> mappings;
private final AnnotationFilter filter;
public AnnotationTypeMappings(AnnotationFilter filter, Class<? extends Annotation> annotationType) {
this.filter = filter;
this.mappings = new ArrayList<>();
//层序遍历元注解
addAllMappings(annotationType);
}
private void addAllMappings(Class<? extends Annotation> annotationType){
//层序遍历辅助队列,双端队列
Deque<AnnotationTypeMapping> deque = new ArrayDeque<>();
addIfPossible(deque, null, annotationType, null);
while (!deque.isEmpty()){
AnnotationTypeMapping mapping = deque.removeFirst();
this.mappings.add(mapping);
//获取下一层注解并添加到队列中
addMetaAnnotationToQueue(deque, mapping);
}
}
/**
* 获取source的元注解添加到deque
* @param deque 队列
* @param source 注解
*/
private void addMetaAnnotationToQueue(Deque<AnnotationTypeMapping> deque, AnnotationTypeMapping source){
//获取到元注解
Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType());
for (Annotation metaAnnotation : metaAnnotations) {
//筛选掉为null,符合filter,还有已经存在的
if (!isMappable(source, metaAnnotation)){
continue;
}
addIfPossible(deque, source, metaAnnotation.annotationType(), metaAnnotation);
}
}
/**
* 向队列中添加AnnotationTypeMapping
* @param deque 队列
* @param annotation 注解
*/
private void addIfPossible(Deque<AnnotationTypeMapping> deque, AnnotationTypeMapping source, Class<? extends Annotation> annotationType, Annotation annotation){
deque.addLast(new AnnotationTypeMapping(source, annotationType, annotation));
}
private boolean isMappable(AnnotationTypeMapping source, Annotation metaAnnotation){
//判断null会把AnnotationsScanner.getDeclaredAnnotations返回数组中的null过滤掉
return (metaAnnotation != null && !this.filter.matches(metaAnnotation)) && !isAlreadyMapped(source, metaAnnotation);
}
/**
* 判断是否已经存在
* 从注解开始下找,如果找到metaAnnotation说明已经存在了
* @param source
* @param metaAnnotation
* @return
*/
private boolean isAlreadyMapped(AnnotationTypeMapping source, Annotation metaAnnotation){
AnnotationTypeMapping mapping = source;
while (mapping != null){
if (mapping.getAnnotationType() == metaAnnotation.annotationType()){
return true;
}
mapping = mapping.getSource();
}
return false;
}
public AnnotationTypeMapping get(int index){
//index == 0 时 就是注解本身
return this.mappings.get(index);
}
/**
* 主要存储 注解->元注解(在AnnotationTypeMappings存储) 关系
* 因为要在静态方法中使用,所有用static修饰
*/
private static class Cache{
private final Map<Class<? extends Annotation>, AnnotationTypeMappings> mappings;
//这里保存注解过滤器是为了传递给AnnotationMappings使用
private AnnotationFilter filter;
public Cache(AnnotationFilter filter) {
this.filter = filter;
this.mappings = new ConcurrentHashMap<>();
}
public AnnotationTypeMappings get(Class<? extends Annotation> annotationType){
//如果不存在就创建
return mappings.computeIfAbsent(annotationType, this::createMappings);
}
public AnnotationTypeMappings createMappings(Class<? extends Annotation> annotationType){
//创建AnnotationTypeMappings的时候,会层序遍历元注解
return new AnnotationTypeMappings(filter, annotationType);
}
}
}