Spring Cache @Cacheable - 从同一 bean 的另一个方法调用时不工作

新手上路,请多包涵

从同一 bean 的另一个方法调用缓存的方法时,Spring 缓存不起作用。

这是一个示例,可以清楚地解释我的问题。

配置:

 <cache:annotation-driven cache-manager="myCacheManager" />

<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
    <property name="cacheManager" ref="myCache" />
</bean>

<!-- Ehcache library setup -->
<bean id="myCache"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true">
    <property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>

<cache name="employeeData" maxElementsInMemory="100"/>

缓存服务:

 @Named("aService")
public class AService {

    @Cacheable("employeeData")
    public List<EmployeeData> getEmployeeData(Date date){
    ..println("Cache is not being used");
    ...
    }

    public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
        List<EmployeeData> employeeData = getEmployeeData(date);
        ...
    }

}

结果 :

 aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used

getEmployeeData 方法调用在第二次调用中按预期使用缓存 employeeData 。但是当在 --- AService 类中调用 getEmployeeData 方法时(在 getEmployeeEnrichedData 中),缓存没有被使用。

这是 spring 缓存的工作方式还是我遗漏了什么?

原文由 Bala 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 954
2 个回答

我相信这就是它的工作原理。根据我记得阅读的内容,生成了一个代理类,它拦截所有请求并使用缓存值进行响应,但同一类中的“内部”调用不会获取缓存值。

来自 https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable

只有通过代理传入的外部方法调用才会被拦截。这意味着自调用实际上是目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法标有@Cacheable,也不会在运行时导致实际的缓存拦截。

原文由 Shawn D. 发布,翻译遵循 CC BY-SA 3.0 许可协议

自 Spring 4.3 以来,可以通过 @Resource 注释使用 自动装配 来解决该问题:

 @Component
@CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {

    /**
     * 1. Self-autowired reference to proxified bean of this class.
     */
    @Resource
    private SphereClientFactory self;

    @Override
    @Cacheable(sync = true)
    public SphereClient createSphereClient(@Nonnull TenantConfig tenantConfig) {
        // 2. call cached method using self-bean
        return self.createSphereClient(tenantConfig.getSphereClientConfig());
    }

    @Override
    @Cacheable(sync = true)
    public SphereClient createSphereClient(@Nonnull SphereClientConfig clientConfig) {
        return CtpClientConfigurationUtils.createSphereClient(clientConfig);
    }
}

原文由 radistao 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题