@Service类中的Spring Boot缓存不起作用 [英] Spring boot caching in @Service class does not work

查看:243
本文介绍了@Service类中的Spring Boot缓存不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用@Service方法保存一些值时遇到问题。
我的代码:

I have problems with save some values in @Service method. My code:

@Service(value = "SettingsService")
public class SettingsService {
...

    public String getGlobalSettingsValue(Settings setting) {
        getTotalEhCacheSize();
        if(!setting.getGlobal()){
            throw new IllegalStateException(setting.name() + " is not global setting");
        }
        GlobalSettings globalSettings = globalSettingsRepository.findBySetting(setting);
        if(globalSettings != null)
            return globalSettings.getValue();
        else
            return getGlobalEnumValue(setting)
    }

@Cacheable(value = "noTimeCache", key = "#setting.name()")
    public String getGlobalEnumValue(Settings setting) {
        return Settings.valueOf(setting.name()).getDefaultValue();
    }

我的存储库类:

@Repository
public interface GlobalSettingsRepository extends CrudRepository<GlobalSettings, Settings> {

    @Cacheable(value = "noTimeCache", key = "#setting.name()", unless="#result == null")
    GlobalSettings findBySetting(Settings setting);

它应该像这样工作:


  • 如果有数据,则从数据库中获取值,

  • 如果未从枚举中保存值。

但它没有保存来自数据库或枚举的任何数据。

but it didn't save any data from DB or enum.

我的缓存配置:

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public EhCacheCacheManager cacheManager(CacheManager cm) {
        return new EhCacheCacheManager(cm);
    }
    @Bean
    public EhCacheManagerFactoryBean ehcache() {
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));

        return  ehCacheManagerFactoryBean;
    }
}

我有一些例子可以确保缓存正常工作在我的项目中的休息方法:

I have some example to make sure that cache is working in my project in rest method:

    @RequestMapping(value = "/system/status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> systemStatus() {
        Object[] list = userPuzzleRepository.getAverageResponseByDateBetween(startDate, endDate);
...
}

public interface UserPuzzleRepository extends CrudRepository<UserPuzzle, Long> {
    @Cacheable(value = "averageTimeAnswer", key = "#startDate")
    @Query("select AVG(case when up.status='SUCCESS' OR up.status='FAILURE' OR up.status='TO_CHECK' then up.solvedTime else null end) from UserPuzzle up where up.solvedDate BETWEEN ?1 AND ?2")
    Object[] getAverageResponseByDateBetween(Timestamp startDate, Timestamp endDate);

它运行良好。

什么我在做错吗?

推荐答案

在您的 SettingsService 中有两种方法,一个被缓存( getGlobalEnumValue(...)),另一个未被缓存但调用另一个方法( getGlobalSettingsValue(。 ..))。

You have two methods in your SettingsService, one that is cached (getGlobalEnumValue(...)) and another one that isn't cached, but calls the other method (getGlobalSettingsValue(...)).

Spring缓存抽象的工作方式是通过代理类(使用 Spring AOP )。但是,对同一类中的方法的调用将不会调用代理逻辑,而是在其下调用直接业务逻辑。这意味着如果您在同一个bean中调用方法,则缓存不起作用。

The way the Spring cache abstraction works however is by proxying your class (using Spring AOP). However, calls to methods within the same class will not call the proxied logic, but the direct business logic beneath. This means caching does not work if you're calling methods in the same bean.

因此,如果您调用 getGlobalSettingsValue(),它将不会填充,也不会在该方法调用 getGlobalEnumValue(...)时使用缓存。

So, if you're calling getGlobalSettingsValue(), it will not populate, nor use the cache when that method calls getGlobalEnumValue(...).

可能的解决方案是:


  1. 不在同一类中调用另一个方法使用代理时

  2. 也缓存另一种方法

  3. 使用AspectJ而不是Spring AOP,它在编译时将代码直接编织到字节码中,而不是代理该类。您可以通过设置 @EnableCaching(mode = AdviceMode.ASPECTJ)来切换模式。但是,您必须

  4. 将该服务自动连接到您的服务中,并使用该服务而不是直接调用该方法。通过自动装配服务,可以将代理注入到您的服务中。

  1. Not calling another method in the same class when using proxies
  2. Caching the other method as well
  3. Using AspectJ rather than Spring AOP, which weaves the code directly into the byte code at compile time, rather than proxying the class. You can switch the mode by setting the @EnableCaching(mode = AdviceMode.ASPECTJ). However, you'll have to set up load time weaving as well.
  4. Autowire the service into your service, and use that service rather than calling the method directly. By autowiring the service, you inject the proxy into your service.

这篇关于@Service类中的Spring Boot缓存不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆