diff --git a/core/src/main/java/cn/qaiu/vx/core/util/ReflectionUtil.java b/core/src/main/java/cn/qaiu/vx/core/util/ReflectionUtil.java index 89a48ba..3853bc3 100644 --- a/core/src/main/java/cn/qaiu/vx/core/util/ReflectionUtil.java +++ b/core/src/main/java/cn/qaiu/vx/core/util/ReflectionUtil.java @@ -18,12 +18,14 @@ import org.reflections.util.FilterBuilder; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; +import java.lang.ref.SoftReference; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.text.ParseException; import java.util.*; +import java.util.concurrent.TimeUnit; import static cn.qaiu.vx.core.util.ConfigConstant.BASE_LOCATIONS; @@ -37,7 +39,26 @@ import static cn.qaiu.vx.core.util.ConfigConstant.BASE_LOCATIONS; public final class ReflectionUtil { // 缓存Reflections实例,避免重复扫描(每次扫描约35K+值,耗时1-3秒,占用大量内存) - private static final Map REFLECTIONS_CACHE = new java.util.concurrent.ConcurrentHashMap<>(); + // 使用 SoftReference 允许 GC 在内存不足时回收,同时添加 TTL 防止长期占用 + private static final Map> REFLECTIONS_CACHE = new java.util.concurrent.ConcurrentHashMap<>(); + private static final long CACHE_TTL_MS = TimeUnit.HOURS.toMillis(1); // 1小时 TTL + private static final Map CACHE_TIMESTAMP = new java.util.concurrent.ConcurrentHashMap<>(); + + /** + * 清理过期的缓存条目 + */ + private static void cleanExpiredCache() { + long now = System.currentTimeMillis(); + Iterator> iterator = CACHE_TIMESTAMP.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (now - entry.getValue() > CACHE_TTL_MS) { + String key = entry.getKey(); + REFLECTIONS_CACHE.remove(key); + iterator.remove(); + } + } + } /** * 以默认配置的基础包路径获取反射器 @@ -49,34 +70,50 @@ public final class ReflectionUtil { } /** - * 获取反射器(带缓存) + * 获取反射器(带缓存,支持 TTL 和 SoftReference) * * @param packageAddress Package address String * @return Reflections object */ public static Reflections getReflections(String packageAddress) { - return REFLECTIONS_CACHE.computeIfAbsent(packageAddress, key -> { - List packageAddressList; - if (key.contains(",")) { - packageAddressList = Arrays.asList(key.split(",")); - } else if (key.contains(";")) { - packageAddressList = Arrays.asList(key.split(";")); - } else { - packageAddressList = Collections.singletonList(key); - } - return createReflections(packageAddressList); - }); + cleanExpiredCache(); + SoftReference ref = REFLECTIONS_CACHE.get(packageAddress); + Reflections reflections = ref != null ? ref.get() : null; + if (reflections != null) { + return reflections; + } + List packageAddressList; + if (packageAddress.contains(",")) { + packageAddressList = Arrays.asList(packageAddress.split(",")); + } else if (packageAddress.contains(";")) { + packageAddressList = Arrays.asList(packageAddress.split(";")); + } else { + packageAddressList = Collections.singletonList(packageAddress); + } + reflections = createReflections(packageAddressList); + REFLECTIONS_CACHE.put(packageAddress, new SoftReference<>(reflections)); + CACHE_TIMESTAMP.put(packageAddress, System.currentTimeMillis()); + return reflections; } /** - * 获取反射器(带缓存) + * 获取反射器(带缓存,支持 TTL 和 SoftReference) * * @param packageAddresses Package address List * @return Reflections object */ public static Reflections getReflections(List packageAddresses) { + cleanExpiredCache(); String cacheKey = String.join(",", packageAddresses); - return REFLECTIONS_CACHE.computeIfAbsent(cacheKey, key -> createReflections(packageAddresses)); + SoftReference ref = REFLECTIONS_CACHE.get(cacheKey); + Reflections reflections = ref != null ? ref.get() : null; + if (reflections != null) { + return reflections; + } + reflections = createReflections(packageAddresses); + REFLECTIONS_CACHE.put(cacheKey, new SoftReference<>(reflections)); + CACHE_TIMESTAMP.put(cacheKey, System.currentTimeMillis()); + return reflections; } private static Reflections createReflections(List packageAddresses) {