注解工具类支持主动清空缓存

This commit is contained in:
huangchengxing 2022-09-22 14:09:19 +08:00
parent bf76657b12
commit dbbccf3fc8
5 changed files with 75 additions and 6 deletions

View File

@ -103,8 +103,8 @@ import java.util.stream.Stream;
* 该属性类型为注解数组且数组中注解被{@link java.lang.annotation.Repeatable}注解
* 则认为被包括的注解为可重复注解<br>
* eg:<br>
* A上存在注解<em>X</em>该注解是一个容器注解内部可重复注解<em>Y</em>
* 包含解析后得到注解<em>X</em>与它包含的可重复注解<em>Y</em>
* A上存在注解<em>X</em>该注解是一个容器注解内部包含可重复注解<em>Y</em>
* 解析<em>X</em>得到注解<em>X</em>与它包含的可重复注解<em>Y</em>
* </li>
* <li>
* {@link AnnotatedElement}存在直接声明的注解该注解与其他根注解皆有相同的元注解
@ -115,6 +115,12 @@ import java.util.stream.Stream;
* </li>
* </ul>
*
* <p><strong>缓存</strong>
* <p>为了避免注解以及{@link AnnotatedElement}层级结构解析过程中的大量反射调用
* 工具类为{@link AnnotatedElement}及其元注解信息进行了缓存<br>
* 缓存功能默认基于{@link WeakConcurrentMap}实现会在gc时自动回收部分缓存数据
* 但是若有必要也可以调用{@link #clearCaches()}方法主动清空缓存
*
* @author huangchengxing
* @see ResolvedAnnotationMapping
* @see GenericAnnotationMapping
@ -650,7 +656,7 @@ public class AnnotatedElementUtil {
* @param element {@link AnnotatedElement}
* @return {@link MetaAnnotatedElement}实例
*/
private static MetaAnnotatedElement<ResolvedAnnotationMapping> getResolvedMetaElementCache(final AnnotatedElement element) {
static MetaAnnotatedElement<ResolvedAnnotationMapping> getResolvedMetaElementCache(final AnnotatedElement element) {
return RESOLVED_ELEMENT_CACHE.computeIfAbsent(element, ele -> MetaAnnotatedElement.create(
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
));
@ -662,7 +668,7 @@ public class AnnotatedElementUtil {
* @param element {@link AnnotatedElement}
* @return {@link MetaAnnotatedElement}实例
*/
private static MetaAnnotatedElement<GenericAnnotationMapping> getMetaElementCache(final AnnotatedElement element) {
static MetaAnnotatedElement<GenericAnnotationMapping> getMetaElementCache(final AnnotatedElement element) {
return ELEMENT_CACHE.computeIfAbsent(element, ele -> MetaAnnotatedElement.create(
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
));
@ -674,7 +680,7 @@ public class AnnotatedElementUtil {
* @param element {@link AnnotatedElement}
* @return {@link MetaAnnotatedElement}实例
*/
private static RepeatableMetaAnnotatedElement<ResolvedAnnotationMapping> getResolvedRepeatableMetaElementCache(final AnnotatedElement element) {
static RepeatableMetaAnnotatedElement<ResolvedAnnotationMapping> getResolvedRepeatableMetaElementCache(final AnnotatedElement element) {
return RESOLVED_REPEATABLE_ELEMENT_CACHE.computeIfAbsent(element, ele -> RepeatableMetaAnnotatedElement.create(
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
));
@ -686,7 +692,7 @@ public class AnnotatedElementUtil {
* @param element {@link AnnotatedElement}
* @return {@link MetaAnnotatedElement}实例
*/
private static RepeatableMetaAnnotatedElement<GenericAnnotationMapping> getRepeatableMetaElementCache(final AnnotatedElement element) {
static RepeatableMetaAnnotatedElement<GenericAnnotationMapping> getRepeatableMetaElementCache(final AnnotatedElement element) {
return REPEATABLE_ELEMENT_CACHE.computeIfAbsent(element, ele -> RepeatableMetaAnnotatedElement.create(
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
));
@ -694,6 +700,26 @@ public class AnnotatedElementUtil {
// endregion
/**
* 清空相关缓存包括
* <ul>
* <li>{@link AnnotatedElementUtil}中的{@link AnnotatedElement}{@link AnnotationMapping}缓存</li>
* <li>{@link AnnotationUtil}中的{@link AnnotatedElement}上直接声明的注解缓存</li>
* <li>{@link RepeatableAnnotationCollector}中单例的注解属性缓存</li>
* </ul>
*
* @see AnnotationUtil#clearCaches()
* @see RepeatableAnnotationCollector#clearSingletonCaches()
*/
public static void clearCaches() {
ELEMENT_CACHE.clear();
RESOLVED_ELEMENT_CACHE.clear();
REPEATABLE_ELEMENT_CACHE.clear();
RESOLVED_REPEATABLE_ELEMENT_CACHE.clear();
RepeatableAnnotationCollector.clearSingletonCaches();
AnnotationUtil.clearCaches();
}
/**
* 由一组注解聚合来的{@link AnnotatedElement}
*/

View File

@ -354,4 +354,11 @@ public class AnnotationUtil {
&& !attribute.isSynthetic();
}
/**
* 清空相关缓存
*/
public static void clearCaches() {
DECLARED_ANNOTATIONS_CACHE.clear();
}
}

View File

@ -86,6 +86,14 @@ public interface RepeatableAnnotationCollector {
return Full.INSTANCE;
}
/**
* 清空单例缓存
*/
static void clearSingletonCaches() {
Standard.INSTANCE.repeatableMethodCache.clear();
Full.INSTANCE.repeatableMethodCache.clear();
}
/**
* <p>若一个注解是可重复注解的容器注解则尝试通过其属性获得获得包含的注解对象
* 若包含的注解对象也是可重复注解的容器注解则继续解析直到获得所有非容器注解为止<br>

View File

@ -37,6 +37,31 @@ public class AnnotatedElementUtilTest {
ANNOTATION6, ANNOTATION5 // Interface.class's annotations
};
@Test
public void testClearCaches() {
AnnotatedElement type = Foo.class;
AnnotatedElement element = AnnotatedElementUtil.getResolvedMetaElementCache(type);
Assert.assertSame(element, AnnotatedElementUtil.getResolvedMetaElementCache(type));
AnnotatedElementUtil.clearCaches();
Assert.assertNotSame(element, AnnotatedElementUtil.getResolvedMetaElementCache(type));
element = AnnotatedElementUtil.getMetaElementCache(type);
Assert.assertSame(element, AnnotatedElementUtil.getMetaElementCache(type));
AnnotatedElementUtil.clearCaches();
Assert.assertNotSame(element, AnnotatedElementUtil.getMetaElementCache(type));
element = AnnotatedElementUtil.getResolvedRepeatableMetaElementCache(type);
Assert.assertSame(element, AnnotatedElementUtil.getResolvedRepeatableMetaElementCache(type));
AnnotatedElementUtil.clearCaches();
Assert.assertNotSame(element, AnnotatedElementUtil.getResolvedRepeatableMetaElementCache(type));
element = AnnotatedElementUtil.getRepeatableMetaElementCache(type);
Assert.assertSame(element, AnnotatedElementUtil.getRepeatableMetaElementCache(type));
AnnotatedElementUtil.clearCaches();
Assert.assertNotSame(element, AnnotatedElementUtil.getRepeatableMetaElementCache(type));
}
@Test
public void testIsAnnotated() {
Assert.assertTrue(AnnotatedElementUtil.isAnnotated(Foo.class, Annotation1.class));

View File

@ -19,6 +19,9 @@ public class AnnotationUtilTest {
Annotation[] annotations = AnnotationUtil.getDeclaredAnnotations(ClassForTest.class);
Assert.assertArrayEquals(annotations, ClassForTest.class.getDeclaredAnnotations());
Assert.assertSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
AnnotationUtil.clearCaches();
Assert.assertNotSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
}
@Test