【问题标题】:@Cachable annotation does not work@Cachable 注解不起作用
【发布时间】:2013-04-10 11:43:09
【问题描述】:

我们在项目中使用 ehcache 进行缓存。

import com.googlecode.ehcache.annotations.Cacheable;
// Other imports

@Component
public class Authenticator{
    @Cacheable(cacheName = "rest_client_authorized")
    public boolean isUserAuthorized(final String user, final String sessionId) {
        // Method code
    }
}

进入方法时没有缓存拦截器。到目前为止我们检查的内容:

  1. 我们不是从类内部调用这个方法,而是从外部调用。所以问题不在于导致绕过代理的内部调用。
  2. 我们为这个类添加了一个接口,并且我们更改了调用这个类的注入,以使用接口表示而不是具体类。

我们以这种方式在应用程序上下文中定义了缓存管理器:

   <ehcache:annotation-driven cache-manager="ehCacheManager" />         
   <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
       <!-- use a share singleton CacheManager -->
       <property name="shared" value="true" />
   </bean>

缓存是这样定义的:

        <cache name="rest_client_authorized"
            eternal="false"
            maxElementsInMemory="50"
            overflowToDisk="false" diskPersistent="false"
            timeToIdleSeconds="0" timeToLiveSeconds="600"
            memoryStoreEvictionPolicy="LRU" />

当我们使用 Jconsole 测试缓存管理器时,我们可以看到缓存 *rest_auth_disabled* 存在且为空。

任何关于为什么这不起作用的想法将不胜感激。谢谢!

更新(来自以下 cmets 的汇总)

===========================================**

这是一个遗留代码,可以很好地与我提供的类和定义配合使用。我在这里谈论的方法是新的,但班上的其他人在过去确实有效。因此,我们正在努力了解发生了什么变化。我们还尝试将注释替换为spring Cacheable,但仍然没有:/ 也许这取决于调用这个新方法的代码,它来自与我们用于其他方法的不同的spring bean。但我还是找不到问题。

还尝试在下面的答案之后返回布尔值而不是布尔值,但它不起作用。 我们有一个新的线索,可能与我们注入 bean 的方式有关(使用@Autowire)。如果确实如此,将更新。

【问题讨论】:

  • 您使用什么持久性提供程序?使用休眠时,见HH-5303
  • 好吧,我们确实使用了 Hibernate。但是我们已经在这个项目中使用了 @Cacheable 并且它有效。缓存缓存在内存中,而不是在 DB 中。另外,请注意这不是 JPA 注释,所以我不确定情况是否如此。你怎么看?
  • 你是对的,我没有阅读实际的导入语句,并认为它是你在谈论的 JPA 注释。你用什么应用服务器?
  • 嗯,我不知道那个服务器。您是否在 persistence.xml 中启用了缓存? ""。不过,我不知道您的服务器是否需要。
  • tc-server 是tomcat7的spring版本,基本一致。即使我没有将数据库用作缓存,是否也需要启用此休眠属性?

标签: java spring ehcache spring-annotations


【解决方案1】:

这个问题可能与 Springs 加载 bean 的顺序有关。尝试从 Authenticator 声明中删除 @Autowire 注释,并手动进行自动装配。比如:

/**
 * Class that uses Authenticator
 */

 public class X {

    // Don't use @autowire here
    public Authenticator athenticator;

    public void doSomething() {
         manuallyAutowire();
    }

    public void manuallyAutowire() {
         if(authenticator == null) {
    authenticator = ApplicationContextUtils.getApplicationContext().
                            getBean(authenticator.class);
    }
}

在哪里

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(final ApplicationContext appContext) 
                                          throws BeansException {
         ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}

【讨论】:

  • 有人能详细说明为什么会这样吗?注释不起作用是非常糟糕的。
【解决方案2】:

@Cacheable中cacheName参数的值应该和声明的name属性的值一致您的应用程序上下文

【讨论】:

  • 你是对的,它是一样的。我只是错误地复制了一个不同的 xml 条目。我修好了它。感谢您的回答!
【解决方案3】:

我认为你在这里混淆了 - 你使用了 com.googlecode.ehcache.annotations.Cacheable,如果你想要 Springs 缓存支持,它实际上应该是 org.springframework.cache.annotation.Cacheable。然后缓存拦截器应该可以正常工作。

【讨论】:

  • 问题是 - 这是一个遗留代码,与我提供的代码和定义一起工作得很好。我在这里谈论的方法是新的,但班上的其他人在过去确实有效。因此,我们正在努力了解发生了什么变化。我们还尝试将注释替换为spring Cacheable,但仍然没有:/
  • 哦,好吧,我不熟悉 ehcache Spring 注解支持,但是如果您使用 Spring 的 @Cacheable(org.spring..) 那么您还必须将 &lt;ehcache:annotation-driven/&gt; 更改为 @987654324 @,在命名空间http://www.springframework.org/schema/cache 中缓存前缀,这应该会为您创建代理。
【解决方案4】:

据我所知,Spring Ehcache 注释建议作为返回对象的两个参数都应具有基本类型所缺少的 equals()hashCode() 方法。

我不确定这个框架是否将原语转换为它们的包装变体(例如IntegerBoolean)。尝试返回包装器变体 Boolean 而不是原始类型,看看它是否有效。

我不确定的另一件事是它如何(以及是否)处理final 参数。如果我的第一个想法行不通,请尝试删除 final 关键字,看看是否可行。

【讨论】:

  • 好的,这些都是很棒的输入!我会检查并报告结果。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-10-22
  • 2013-05-15
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多