【问题标题】:Can't evict from Spring Cache in Guice DI app无法从 Guice DI 应用程序中的 Spring Cache 中逐出
【发布时间】:2013-04-06 19:04:16
【问题描述】:

我正在尝试将字符串缓存抽象机制与 guice 模块一起使用。 我已经创建了拦截器:

CacheManager cacheManager = createCacheManager(); 绑定(CacheManager.class).toInstance(cacheManager);

    AppCacheInterceptor interceptor = new AppCacheInterceptor(
            cacheManager,
            createCacheOperationSource()
    );

    bindInterceptor(
            Matchers.any(),
            Matchers.annotatedWith(Cacheable.class),
            interceptor
    );

    bindInterceptor(
            Matchers.any(),
            Matchers.annotatedWith(CacheEvict.class),
            interceptor
    );

然后,实现了Strings Cache接口和CacheManager,最后用@Cachable和@CacheEvict注解了我的DAO类:

public class DaoTester {

QssandraConsumer qs;

@CachePut(value = "cached_consumers", key = "#consumer.id")
public void save(QssandraConsumer consumer) {
    qs = consumer;
}

@Cacheable(value = "cached_consumers")
public QssandraConsumer get(String id) {
    if (id != null) {
        qs.getId();
    }
    return qs;
}

@CacheEvict(value = "cached_consumers", key = "#consumer.id")
public void remove(QssandraConsumer consumer) {
    qs = consumer;
}}

缓存很好 - 这里没有问题,但是当我尝试驱逐(在本例中调用 remove 方法)时,evrything 崩溃了,我看到了:

线程“main”中的异常 org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 10): Field or property 'id' cannot be found on null 在 org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:205) 在 org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72) 在 org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57) 在 org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93) 在 org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88) 在 org.springframework.cache.interceptor.ExpressionEvaluator.key(ExpressionEvaluator.java:80) 在 org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:464) 在 org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheEvicts(CacheAspectSupport.java:260) 在 org.springframework.cache.interceptor.CacheAspectSupport.inspectAfterCacheEvicts(CacheAspectSupport.java:232) 在 org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:215) 在 org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) 在 qiwi.qommon.deployment.dao.DaoTester.main(DaoTester.java:44) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

这里有什么问题?! 顺便说一句,缓存的对象是:

public class QssandraConsumer implements Identifiable<String> {
private String id;
private String host;

@Override
public String getId() {
    return id;
}

@Override
public void setId(String id) {
    this.id = id;
}

public String getHost() {
    return host;
}

public void setHost(String host) {
    this.host = host;
}

@Override
public boolean equals(Object object) {
    if (this == object) {
        return true;
    }
    if (null == object) {
        return false;
    }


    if (!(object instanceof QssandraConsumer)) {
        return false;
    }

    QssandraConsumer o = (QssandraConsumer) object;

    return
        Objects.equal(id, o.id)
            && Objects.equal(host, o.host);
}

@Override
public int hashCode() {
    return Objects.hashCode(
        id, host
    );
}

@Override
public String toString() {
    return Objects.toStringHelper(this)
        .addValue(id)
        .addValue(host)
        .toString();
}

}

【问题讨论】:

    标签: spring caching guice


    【解决方案1】:

    最后我弄清楚了问题的原因: 当注入一个使用注解的类时(被拦截,如@Cachable@CacheEvict)Guice 增强了类(AOP 在运行时进行字节码修改)。因此,当CacheInterceptor 尝试评估key = "#consumer.id" 时,它失败了,因为在增强类中找不到参数名称(请参阅:LocalVariableTableParameterNameDiscoverer#inspectClass)。 所以它不能在 Guice 中开箱即用。 在春季创建代理类 - 所以这里没有问题。

    【讨论】:

      猜你喜欢
      • 2021-06-12
      • 2015-11-18
      • 2013-03-24
      • 1970-01-01
      • 2020-09-15
      • 2012-05-17
      • 2021-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多