如何使 Spring Framework 的 @Cachable 以文件的 lastModified 属性 作为键?

How can I make Spring Framework 's @Cachable work with lastModified property of a File as key?

这是我的代码:

@Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
private Object foo(File myFile) throws IOException {
    System.out.println(myFile.lastModified());
    try {
        Thread.sleep(6000);
    } catch (InterruptedException ignored) {

    }
    final Object foo = new SomeObjectFromFile(myFile);
    return foo;
}

我两次调用此方法传递具有相同 lastmodified 值的文件对象,但缓存不起作用,该方法将等待 6 秒。

这是我得到的输出:

1456298573000
1456298573000

我做错了什么?

key = "#myFile.lastModified"

也没用..

我确定我的 ehcache 配置没问题。

问题在于您的方法是私有的。

documentation of the Spring Framework所述:

Method visibility and cache annotations

When using proxies, you should apply the cache annotations only to methods with public visibility. If you do annotate protected, private or package-visible methods with these annotations, no error is raised, but the annotated method does not exhibit the configured caching settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods as it changes the bytecode itself.

[...]

In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual caching at runtime even if the invoked method is marked with @Cacheable - considering using the aspectj mode in this case. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.

您应该切换到 public 方法并进行外部调用或用户 AspectJ。

假设您不使用 aspectj,Juliens 的回答可能是正确的。它不是单独调用 public 方法,而是调用对象的 public 方法,其中 spring 有机会包装它的代理。因此,请确保您正在注入希望通过可缓存支持得到增强的服务。

例如

@Service
public SomeService {
    @Autowired
    private CacheEnhancedService css;

    public void doSomething() {
        css.getConfig(new File("./file"));
     }
}

@Service
public CacheEnhancedService {
    @Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
    public Object getConfig(File myFile) {
        ...
     }
 }
}