【问题标题】:Spring 5 cache not work for @Cachable (CacheInterceptor is not in call stack)?Spring 5 缓存不适用于 @Cachable(CacheInterceptor 不在调用堆栈中)?
【发布时间】:2018-10-05 21:27:08
【问题描述】:

我通过添加@Cachable 注释为公共方法启用缓存,如下所示:

@Cacheable(cacheNames = "saas_setting", //
        key = "#key")
public Setting get(String key) { ... }

另一方面,我添加了 cacheManager bean:

<bean id="cacheManager"
    class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
        <set>
            <bean
                class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                name="saas_setting" />
        </set>
    </property>
</bean>

我启用 AOP:

<aop:aspectj-autoproxy 
    proxy-target-class="true"/>

然后启用缓存:

<cache:annotation-driven 
    mode="aspectj"
    proxy-target-class="true"/>

但是,结果不会被缓存,并且当从系统的其他部分调用该方法时会调用该方法。

我在方法中放了一个刹车点,检查调用堆栈:堆栈中没有CachInterceptor?!


编辑:

这是完整的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-4.3.xsd">

    <!-- Enable AspectJ style of Spring AOP -->
    <aop:aspectj-autoproxy 
        proxy-target-class="true"/>

    <!-- Enable cache -->
    <cache:annotation-driven 
        mode="aspectj"
        proxy-target-class="true"/>


    <bean id="cacheManager"
        class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean
                    class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                    name="saas_setting" />
            </set>
        </property>
    </bean>

    <bean name="applicationProperties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreResourceNotFound" value="false" />
        <property name="locations">
            <list>
                <value>resources/server.properties</value>
                <value>resources/modules/*.properties</value>
                <value>resources/jetty/*.properties</value>
                <value>resources/db/#{systemProperties['db.dialect']}.properties
                </value>
                <value>resources/db/#{systemProperties['db.orm']}.properties</value>
            </list>
        </property>
    </bean>
    <import resource="../context/beans-*.xml" />
</beans>

编辑:

基于 Spring 文档:

处理缓存注释的默认建议模式是“代理”,它只允许通过代理拦截调用;同一类中的本地调用不能以这种方式被拦截。对于更高级的拦截模式,请考虑切换到“aspectj”模式并结合编译时或加载时编织。

在我的代码的某些部分,私有方法将被缓存。所以我必须将 AspectJ 与加载时编织一起使用。

【问题讨论】:

  • 请添加完整的xml配置

标签: java spring caching aop


【解决方案1】:

因为您使用的是 aspectJ 缓存模式,所以您的类路径中需要 spring-aspects.jar。不清楚为什么要使用 aspectj 代理而不是默认代理。

由于您使用 aspectj 模式进行代理,因此您还需要设置加载时间编织。

可以使用以下方式启用加载时间编织:

<context:load-time-weaver/>

您使用的方法也必须来自具体类,因为您使用的是proxy-target-class="true"

【讨论】:

  • 亲爱的 Sangam,我如何检查缓存是否正常工作或故障排除?是否可以调试和跟踪spring代码并找到原因?
猜你喜欢
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
相关资源
最近更新 更多