All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.magictools.core.annotation.scanner.MetaAnnotationScanner Maven / Gradle / Ivy

Go to download

magic-tools 是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

The newest version!
package com.magictools.core.annotation.scanner;

import com.magictools.core.annotation.AnnotationUtil;
import com.magictools.core.collection.CollStreamUtil;
import com.magictools.core.collection.CollUtil;
import com.magictools.core.util.ClassUtil;
import com.magictools.core.util.ObjectUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 扫描注解类上存在的注解,支持处理枚举实例或枚举类型
 * 需要注意,当待解析是枚举类时,有可能与{@link TypeAnnotationScanner}冲突
 *
 * @author huangchengxing
 * @see TypeAnnotationScanner
 */
public class MetaAnnotationScanner implements AnnotationScanner {

	/**
	 * 获取当前注解的元注解后,是否继续递归扫描的元注解的元注解
	 */
	private final boolean includeSupperMetaAnnotation;

	/**
	 * 构造
	 *
	 * @param includeSupperMetaAnnotation 获取当前注解的元注解后,是否继续递归扫描的元注解的元注解
	 */
	public MetaAnnotationScanner(boolean includeSupperMetaAnnotation) {
		this.includeSupperMetaAnnotation = includeSupperMetaAnnotation;
	}

	/**
	 * 构造一个元注解扫描器,默认在扫描当前注解上的元注解后,并继续递归扫描元注解
	 */
	public MetaAnnotationScanner() {
		this(true);
	}

	@Override
	public boolean support(AnnotatedElement annotatedElement) {
		return (annotatedElement instanceof Class && ClassUtil.isAssignable(Annotation.class, (Class) annotatedElement));
	}

	/**
	 * 按广度优先扫描指定注解上的元注解,对扫描到的注解与层级索引进行操作
	 *
	 * @param consumer 当前层级索引与操作
	 * @param source   源注解
	 * @param filter   过滤器
	 * @author huangchengxing
	 */
	public void scan(BiConsumer consumer, Class source, Predicate filter) {
		filter = ObjectUtil.defaultIfNull(filter, t -> true);
		final Deque>> deque = CollUtil.newLinkedList(CollUtil.newArrayList(source));
		int distance = 0;
		do {
			final List> annotationTypes = deque.removeFirst();
			for (final Class type : annotationTypes) {
				final List metaAnnotations = Stream.of(type.getAnnotations())
						.filter(a -> !AnnotationUtil.isJdkMetaAnnotation(a.annotationType()))
						.filter(filter)
						.collect(Collectors.toList());
				for (final Annotation metaAnnotation : metaAnnotations) {
					consumer.accept(distance, metaAnnotation);
				}
				deque.addLast(CollStreamUtil.toList(metaAnnotations, Annotation::annotationType));
			}
			distance++;
		} while (includeSupperMetaAnnotation && !deque.isEmpty());
	}

	@SuppressWarnings("unchecked")
	@Override
	public List getAnnotations(AnnotatedElement annotatedElement) {
		final List annotations = new ArrayList<>();
		scan(
				(index, annotation) -> annotations.add(annotation),
				(Class) annotatedElement,
				annotation -> ObjectUtil.notEqual(annotation, annotatedElement)
		);
		return annotations;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy