mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
注解工具类支持主动清空缓存
This commit is contained in:
parent
bf76657b12
commit
dbbccf3fc8
@ -103,8 +103,8 @@ import java.util.stream.Stream;
|
|||||||
* 该属性类型为注解数组,且数组中注解被{@link java.lang.annotation.Repeatable}注解,
|
* 该属性类型为注解数组,且数组中注解被{@link java.lang.annotation.Repeatable}注解,
|
||||||
* 则认为被包括的注解为可重复注解;<br>
|
* 则认为被包括的注解为可重复注解;<br>
|
||||||
* eg:<br>
|
* eg:<br>
|
||||||
* A上存在注解<em>X</em>,该注解是一个容器注解,内部可重复注解<em>Y</em>,
|
* A上存在注解<em>X</em>,该注解是一个容器注解,内部包含可重复注解<em>Y</em>,
|
||||||
* 包含解析后,得到注解<em>X</em>与它包含的可重复注解<em>Y</em>;
|
* 解析<em>X</em>后,得到注解<em>X</em>与它包含的可重复注解<em>Y</em>;
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* 若{@link AnnotatedElement}存在直接声明的注解,该注解与其他根注解皆有相同的元注解,
|
* 若{@link AnnotatedElement}存在直接声明的注解,该注解与其他根注解皆有相同的元注解,
|
||||||
@ -115,6 +115,12 @@ import java.util.stream.Stream;
|
|||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* <p><strong>缓存</strong>
|
||||||
|
* <p>为了避免注解以及{@link AnnotatedElement}层级结构解析过程中的大量反射调用,
|
||||||
|
* 工具类为{@link AnnotatedElement}及其元注解信息进行了缓存。<br>
|
||||||
|
* 缓存功能默认基于{@link WeakConcurrentMap}实现,会在gc时自动回收部分缓存数据。
|
||||||
|
* 但是若有必要,也可以调用{@link #clearCaches()}方法主动清空缓存。
|
||||||
|
*
|
||||||
* @author huangchengxing
|
* @author huangchengxing
|
||||||
* @see ResolvedAnnotationMapping
|
* @see ResolvedAnnotationMapping
|
||||||
* @see GenericAnnotationMapping
|
* @see GenericAnnotationMapping
|
||||||
@ -650,7 +656,7 @@ public class AnnotatedElementUtil {
|
|||||||
* @param element {@link AnnotatedElement}
|
* @param element {@link AnnotatedElement}
|
||||||
* @return {@link MetaAnnotatedElement}实例
|
* @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(
|
return RESOLVED_ELEMENT_CACHE.computeIfAbsent(element, ele -> MetaAnnotatedElement.create(
|
||||||
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
|
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
|
||||||
));
|
));
|
||||||
@ -662,7 +668,7 @@ public class AnnotatedElementUtil {
|
|||||||
* @param element {@link AnnotatedElement}
|
* @param element {@link AnnotatedElement}
|
||||||
* @return {@link MetaAnnotatedElement}实例
|
* @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(
|
return ELEMENT_CACHE.computeIfAbsent(element, ele -> MetaAnnotatedElement.create(
|
||||||
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
|
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
|
||||||
));
|
));
|
||||||
@ -674,7 +680,7 @@ public class AnnotatedElementUtil {
|
|||||||
* @param element {@link AnnotatedElement}
|
* @param element {@link AnnotatedElement}
|
||||||
* @return {@link MetaAnnotatedElement}实例
|
* @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(
|
return RESOLVED_REPEATABLE_ELEMENT_CACHE.computeIfAbsent(element, ele -> RepeatableMetaAnnotatedElement.create(
|
||||||
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
|
element, (source, annotation) -> ResolvedAnnotationMapping.create(source, annotation, true)
|
||||||
));
|
));
|
||||||
@ -686,7 +692,7 @@ public class AnnotatedElementUtil {
|
|||||||
* @param element {@link AnnotatedElement}
|
* @param element {@link AnnotatedElement}
|
||||||
* @return {@link MetaAnnotatedElement}实例
|
* @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(
|
return REPEATABLE_ELEMENT_CACHE.computeIfAbsent(element, ele -> RepeatableMetaAnnotatedElement.create(
|
||||||
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
|
element, (source, annotation) -> GenericAnnotationMapping.create(annotation, Objects.isNull(source))
|
||||||
));
|
));
|
||||||
@ -694,6 +700,26 @@ public class AnnotatedElementUtil {
|
|||||||
|
|
||||||
// endregion
|
// 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}
|
* 由一组注解聚合来的{@link AnnotatedElement}
|
||||||
*/
|
*/
|
||||||
|
@ -354,4 +354,11 @@ public class AnnotationUtil {
|
|||||||
&& !attribute.isSynthetic();
|
&& !attribute.isSynthetic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空相关缓存
|
||||||
|
*/
|
||||||
|
public static void clearCaches() {
|
||||||
|
DECLARED_ANNOTATIONS_CACHE.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,14 @@ public interface RepeatableAnnotationCollector {
|
|||||||
return Full.INSTANCE;
|
return Full.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空单例缓存
|
||||||
|
*/
|
||||||
|
static void clearSingletonCaches() {
|
||||||
|
Standard.INSTANCE.repeatableMethodCache.clear();
|
||||||
|
Full.INSTANCE.repeatableMethodCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>若一个注解是可重复注解的容器注解,则尝试通过其属性获得获得包含的注解对象。
|
* <p>若一个注解是可重复注解的容器注解,则尝试通过其属性获得获得包含的注解对象。
|
||||||
* 若包含的注解对象也是可重复注解的容器注解,则继续解析直到获得所有非容器注解为止。<br>
|
* 若包含的注解对象也是可重复注解的容器注解,则继续解析直到获得所有非容器注解为止。<br>
|
||||||
|
@ -37,6 +37,31 @@ public class AnnotatedElementUtilTest {
|
|||||||
ANNOTATION6, ANNOTATION5 // Interface.class's annotations
|
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
|
@Test
|
||||||
public void testIsAnnotated() {
|
public void testIsAnnotated() {
|
||||||
Assert.assertTrue(AnnotatedElementUtil.isAnnotated(Foo.class, Annotation1.class));
|
Assert.assertTrue(AnnotatedElementUtil.isAnnotated(Foo.class, Annotation1.class));
|
||||||
|
@ -19,6 +19,9 @@ public class AnnotationUtilTest {
|
|||||||
Annotation[] annotations = AnnotationUtil.getDeclaredAnnotations(ClassForTest.class);
|
Annotation[] annotations = AnnotationUtil.getDeclaredAnnotations(ClassForTest.class);
|
||||||
Assert.assertArrayEquals(annotations, ClassForTest.class.getDeclaredAnnotations());
|
Assert.assertArrayEquals(annotations, ClassForTest.class.getDeclaredAnnotations());
|
||||||
Assert.assertSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
|
Assert.assertSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
|
||||||
|
|
||||||
|
AnnotationUtil.clearCaches();
|
||||||
|
Assert.assertNotSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user