@Service类中的Spring Boot缓存不起作用

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

@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);

它应该像这样工作:

  • 如果数据存在,则从DB获得价值,
  • 如果没有,则从枚举中保存价值。

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

我的缓存配置:

@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;

}

}

我有一些示例来确保缓存在我的项目中以rest方法运行:

    @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(...))。

但是,Spring缓存抽象的工作方式是通过代理类(使用Spring

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

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


可能的解决方案是:

  1. 使用代理时未在同一类中调用另一个方法
  2. 也缓存另一种方法
  3. 使用AspectJ而不是Spring AOP,它在编译时将代码直接编织到字节代码中,而不是代理类。您可以通过设置来切换模式@EnableCaching(mode = AdviceMode.ASPECTJ)。但是,您还必须设置加载时间编织。
  4. 将服务自动连接到您的服务中,并使用该服务,而不是直接调用该方法。通过自动装配服务,您可以将代理注入到您的服务中。

以上是 @Service类中的Spring Boot缓存不起作用 的全部内容, 来源链接: utcz.com/qa/423571.html

回到顶部