我认为您使用了错误的缓存键。您应该使用由方法参数的表示组成的缓存键,而不是方法名称。否则,无论使用哪个参数,对于每个方法调用,您总是会从缓存中获得完全相同的结果。
这里有一点MCVE,使用单例方面:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(METHOD)
public @interface Memoized {
String value();
}
package de.scrum_master.app;
import org.aspectj.lang.Aspects;
import de.scrum_master.aspect.Memoize;
public class Application {
public static void main(String[] args) {
Application application;
for (int i = 0; i < 3; i++) {
application = new Application();
System.out.println(application.capitalise("foo"));
System.out.println(application.triple(11));
System.out.println(application.capitalise("bar"));
System.out.println(application.triple(22));
}
Aspects.aspectOf(Memoize.class).printCacheStats();
}
@Memoized("PT1M45S")
public String capitalise(String string) {
System.out.println("Capitalising " + string);
return string.toUpperCase();
}
@Memoized("PT1H30M")
public int triple(int i) {
System.out.println("Tripling " + i);
return 3 * i;
}
}
package de.scrum_master.aspect;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.aspectj.lang.SoftException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import de.scrum_master.app.Memoized;
public aspect Memoize {
private final Map<String, Cache<String, Object>> caches = new HashMap<>();
public pointcut memoized(Memoized memoized) : execution(* *(..)) && @annotation(memoized);
Object around(Memoized memoized): memoized(memoized) {
String cacheID = thisJoinPoint.getSignature().toString();
Cache<String, Object> cache = caches.get(cacheID);
if (cache == null) {
cache = CacheBuilder.newBuilder().recordStats().expireAfterWrite(Duration.parse(memoized.value())).build();
caches.put(cacheID, cache);
}
System.out.println(thisJoinPoint + " -> " + cache);
String args = Arrays.deepToString(thisJoinPoint.getArgs());
try {
return cache.get(cacheID + "#" + args, () -> proceed(memoized));
} catch (ExecutionException e) {
throw new SoftException(e);
}
}
public void printCacheStats() {
caches.entrySet().forEach(entry -> System.out.println(entry.getKey() + " -> " +entry.getValue().stats()));
}
}
如您所见,我在方面添加了一个额外的方法,因此我们可以在控制台上看到一些统计信息。在运行驱动程序应用程序时,我们预计这两种方法中的每一种都有 2 次缓存未命中和 4 次命中。让我们找出控制台日志的内容:
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
Capitalising foo
FOO
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
Tripling 11
33
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
Capitalising bar
BAR
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
Tripling 22
66
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
FOO
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
33
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
BAR
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
66
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
FOO
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
33
execution(String de.scrum_master.app.Application.capitalise(String)) -> com.google.common.cache.LocalCache$LocalManualCache@4ee285c6
BAR
execution(int de.scrum_master.app.Application.triple(int)) -> com.google.common.cache.LocalCache$LocalManualCache@7dc5e7b4
66
String de.scrum_master.app.Application.capitalise(String) -> CacheStats{hitCount=4, missCount=2, loadSuccessCount=2, loadExceptionCount=0, totalLoadTime=19678400, evictionCount=0}
int de.scrum_master.app.Application.triple(int) -> CacheStats{hitCount=4, missCount=2, loadSuccessCount=2, loadExceptionCount=0, totalLoadTime=252000, evictionCount=0}
多多! ?