java Sping Boot -如何在开发过程中禁用@Cacheable?

kqqjbcuj  于 2023-11-15  发布在  Java
关注(0)|答案(6)|浏览(223)

我在找两样东西:
1.如何在开发过程中使用Sping Boot “dev”profile禁用所有缓存。application.properties中似乎没有一个通用的设置来关闭它。最简单的方法是什么?
1.如何禁用特定方法的缓存?我试着像这样使用SpEl:

@Cacheable(value = "complex-calc", condition="#${spring.profiles.active} != 'dev'}")
public String someBigCalculation(String input){
   ...
}

字符串
但是我可以让它工作。SO上有几个问题与此相关,但它们涉及XML config或其他东西,但我使用的是Sping Boot 1.3.3,这使用了自动配置。
我不想把事情弄得太复杂

kjthegm6

kjthegm61#

默认情况下,缓存类型是自动检测和配置的。但是,您可以通过将spring.cache.type添加到配置中来指定要使用的缓存类型。要禁用它,请将值设置为NONE
如果您想为特定的配置文件执行此操作,请将其添加到该配置文件application.properties(在本例中,修改application-dev.properties并添加

spring.cache.type=NONE

字符串
这将禁用缓存。

jslywgbw

jslywgbw2#

David Newcomb comment说的是实话:
spring.cache.type=NONE并没有关闭缓存,它阻止了缓存。也就是说,它仍然向你的程序添加了27层AOP/拦截器堆栈,只是它没有做缓存。这取决于他所说的“把它全部关闭”是什么意思。
使用此选项可能会加快应用程序的启动速度,但也可能会产生一些开销。

1)完全禁用Spring Cache功能

@EnableCaching类移动到一个专用的配置类中,我们将用@Profile Package 以启用它:

@Profile("!dev")
@EnableCaching
@Configuration
public class CachingConfiguration {}

字符串
当然,如果你已经有一个Configuration类,除了dev环境之外,其他环境都可以使用,那么就重用它吧:

@Profile("!dev")
//... any other annotation 
@EnableCaching
@Configuration
public class NoDevConfiguration {}

2)使用假的(noop)缓存管理器

在某些情况下,通过配置文件激活@EnableCaching是不够的,因为您的一些类或应用程序的一些Spring依赖项期望从Spring容器中检索实现org.springframework.cache.CacheManager接口的bean。
在这种情况下,正确的方法是使用一个假的实现,这将允许Spring解决所有依赖关系,而CacheManager的实现是无开销的。
我们可以通过使用@Bean@Profile来实现它:

import org.springframework.cache.support.NoOpCacheManager; 

@Configuration
public class CacheManagerConfiguration {

    @Bean
    @Profile("!dev")
    public CacheManager getRealCacheManager() {
        return new CaffeineCacheManager(); 
        // or any other implementation
        // return new EhCacheCacheManager(); 
    }

    @Bean
    @Profile("dev")
    public CacheManager getNoOpCacheManager() {
        return new NoOpCacheManager();
    }
}


或者,如果它更合适,您可以添加spring.cache.type=NONE属性,该属性将产生与M.代努姆答案中所写的相同的结果。

vsmadaxz

vsmadaxz3#

如果你只有一个默认配置文件,不想为此创建一个开发和生产配置文件,我认为这可能是一个非常快速的解决方案:
application.properties中设置:

appconfig.enablecache=true

字符串
根据您的需求,您可以将其更改为true/false
现在,在定义@Caching bean时,请执行以下操作:

@Bean
public CacheManager cacheManager(@Value("${appconfig.enablecache}") String enableCaching) {
    if (enableCaching.equals("true")) {
        return new EhCacheCacheManager();
        //Add your Caching Implementation here.
    }
    return new NoOpCacheManager();
}


当属性设置为false时,将返回NoOpCacheManager(),从而有效地关闭缓存。

mlnl4t2r

mlnl4t2r4#

对于你的第二个问题,做这样的事情:
编写一个方法来确定一个特定的配置文件是否是活动的(环境是您注入的Environment)

boolean isProfileActive(String profile) { 
   return Arrays.asList(environment.getActiveProfiles()).contains(profile);
}

字符串
然后将其用于可缓存注解上的缓存条件

5lhxktic

5lhxktic5#

在任何类中,您都可以在每个方法的基础上全局启用或禁用缓存,您可以执行以下操作,这允许您在类级别控制如何缓存方法。
您可以在application.properties中使用my.cache.enabled=true更改它。此设置当前默认为启用。
当然,你也可以在application-dev.properties中修改它,并将其设置为不同的值。这种方法的优点是,如果你出于某种原因需要,它可以让这个过程变得更复杂,也可以在每个方法的基础上。

public class MyClass {

  @Value("${my.cache.enabled:true}")
  public String isMyCacheEnabled;

  public boolean isMyCacheEnabled() {
    return (isMyCacheEnabled == null) || isMyCacheEnabled.equals("") || Boolean.valueOf(isMyCacheEnabled);
  }

  @Cacheable(
      cacheManager = "myCacheManager",
      cacheNames = "myCacheKey",
      condition = "#root.target.isMyCacheEnabled()",
      key = "#service + '-' + #key")
  public String getMyValue(String service, String key) {
    // do whatever you normally would to get your value
    return "some data" + service + key;
  }
}

字符串

yizd12fk

yizd12fk6#

你可以在org. springframework. cache. annotation. CachingConfigurer中使用Web 4j-spring-boot 2依赖项。这个解决方案将与最新的Spring-boot版本6.x一起工作。它对我很有效。

下面是代码片段:
Pom.xml:

<dependency>
  <groupId>io.github.resilience4j</groupId>
  <artifactId>resilience4j-spring-boot2</artifactId>
  <version>2.1.0</version>
</dependency>

字符串

缓存配置类:

package com.redis.sample;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CachingConfiguration implements CachingConfigurer   {  
@Override
public CacheErrorHandler errorHandler() {
return new CustomCacheErrorHandler();
}
}

CustomCacheErrorClass:

package com.redis.sample;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.stereotype.Component;

@Component
public class CustomCacheErrorHandler implements CacheErrorHandler {
 
@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
//do something as per usecase
}

@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
//do something as per usecase
}

@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
//do something as per usecase
}

@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
//do something as per usecase
}
}

CircuitBreakerConfig.java配置类:

package com.redis.sample;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
@Configuration
public class CircuitBreakerConfig {

@Bean
  public CircuitBreakerRegistry circuitBreakerRegistry() {
    io.github.resilience4j.circuitbreaker.CircuitBreakerConfig config = io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.custom()
     .failureRateThreshold(6)
        .permittedNumberOfCallsInHalfOpenState(2)
        .slidingWindowSize(5)
        .minimumNumberOfCalls(5)
        .build();
    return CircuitBreakerRegistry.of(config);
  }
 
@Bean
public CircuitBreaker defaultCircuitBreaker() {
  io.github.resilience4j.circuitbreaker.CircuitBreakerConfig config = io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.custom()
      .minimumNumberOfCalls(2)
      .build();
  return CircuitBreaker.of("default", config);
}
}

相关问题