@CacheableにTTLを設定できますか


100

@CacheableSpring 3.1のアノテーションサポートを試してみて、TTLを設定して、キャッシュされたデータをしばらくしてクリアにする方法があるかどうか疑問に思っていますか?今私が見ることができるものから、を使用して自分でそれをクリアする必要があります。それ@CacheEvictを一緒に使用@Scheduledすることで、TTL実装を自分で作成できますが、そのような単純なタスクでは少し多く見えますか?

回答:


39

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#cache-specific-configを参照してください

TTL / TTI /エビクションポリシー/ XXX機能を設定するにはどうすればよいですか?

キャッシュプロバイダーを介して直接。キャッシュの抽象化は...まあ、抽象化はキャッシュの実装ではありません

したがって、EHCacheを使用する場合は、EHCacheの構成を使用してTTLを構成します。

GuavaのCacheBuilderを使用してキャッシュを構築し、このキャッシュのConcurrentMapビューをConcurrentMapCacheFactoryBeanのsetStoreメソッドに渡すこともできます。


57

Spring 3.1およびGuava 1.13.1:

@EnableCaching
@Configuration
public class CacheConfiguration implements CachingConfigurer {

    @Override
    public CacheManager cacheManager() {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() {

            @Override
            protected Cache createConcurrentMapCache(final String name) {
                return new ConcurrentMapCache(name,
                    CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(100).build().asMap(), false);
            }
        };

        return cacheManager;
    }

    @Override
    public KeyGenerator keyGenerator() {
        return new DefaultKeyGenerator();
    }

}

21
Spring 4.1では、CachingConfigurerSupportを拡張し、cacheManager()のみを上書きします。
JohannesFlügel16年

39

SpringでGuava Cacheを設定する完全な例を次に示します。EhcacheでGuavaを使用したのは、それが少し軽量で、構成がわかりやすいためです。

Maven依存関係のインポート

これらの依存関係をmaven pomファイルに追加し、クリーンパッケージを実行します。これらのファイルは、CacheBuilderで使用するGuava depおよびSpringヘルパーメソッドです。

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>18.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>

キャッシュを構成する

Java構成を使用してキャッシュを構成するには、CacheConfigファイルを作成する必要があります。

@Configuration
@EnableCaching
public class CacheConfig {

   public final static String CACHE_ONE = "cacheOne";
   public final static String CACHE_TWO = "cacheTwo";

   @Bean
   public Cache cacheOne() {
      return new GuavaCache(CACHE_ONE, CacheBuilder.newBuilder()
            .expireAfterWrite(60, TimeUnit.MINUTES)
            .build());
   }

   @Bean
   public Cache cacheTwo() {
      return new GuavaCache(CACHE_TWO, CacheBuilder.newBuilder()
            .expireAfterWrite(60, TimeUnit.SECONDS)
            .build());
   }
}

キャッシュされるメソッドに注釈を付ける

@Cacheableアノテーションを追加し、キャッシュ名を渡します。

@Service
public class CachedService extends WebServiceGatewaySupport implements CachedService {

    @Inject
    private RestTemplate restTemplate;


    @Cacheable(CacheConfig.CACHE_ONE)
    public String getCached() {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<String> reqEntity = new HttpEntity<>("url", headers);

        ResponseEntity<String> response;

        String url = "url";
        response = restTemplate.exchange(
                url,
                HttpMethod.GET, reqEntity, String.class);

        return response.getBody();
    }
}

注釈付きのスクリーンショットを使用して、ここでより完全な例を確認できます: SpringのGuava Cache


2
注:グアバキャッシュは現在、春5(で廃止されstackoverflow.com/questions/44175085/...
アミンZiaei

33

私はこのようにライフハッキングを使用しています

@Configuration
@EnableCaching
@EnableScheduling
public class CachingConfig {
    public static final String GAMES = "GAMES";
    @Bean
    public CacheManager cacheManager() {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(GAMES);

        return cacheManager;
    }

@CacheEvict(allEntries = true, value = {GAMES})
@Scheduled(fixedDelay = 10 * 60 * 1000 ,  initialDelay = 500)
public void reportCacheEvict() {
    System.out.println("Flush Cache " + dateFormat.format(new Date()));
}

reportCacheEvictどこからでもメソッドを呼び出していますか?どのようにcacheEvictが発生しますか?
Jaikrat 2016

それを得る。このメソッドをどこからも呼び出していません。fixedDelay時間間隔後に呼び出されます。ヒントをありがとう。
Jaikrat 2016

1
スケジュールに基づいてキャッシュ全体をクリアすることは、物事を機能させるための便利なハックになる可能性がありますが、このメソッドを使用してアイテムにTTLを与えることはできません。条件値でさえ、キャッシュ全体を削除するかどうかを宣言することしかできません。これの根底には、ConcurrentMapCacheがタイムスタンプなしでオブジェクトを格納するという事実があるため、TTLをそのまま評価する方法はありません。
jmb 2017年

パンツのコードです(この方法は落書きされていました:))。
Atum

ナイスでクリーンなアプローチ
ラウクサス

30

Springboot 1.3.8

import java.util.concurrent.TimeUnit;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.cache.CacheBuilder;

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

@Override
@Bean
public CacheManager cacheManager() {
    GuavaCacheManager cacheManager = new GuavaCacheManager();
    return cacheManager;
}

@Bean
public CacheManager timeoutCacheManager() {
    GuavaCacheManager cacheManager = new GuavaCacheManager();
    CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(5, TimeUnit.SECONDS);
    cacheManager.setCacheBuilder(cacheBuilder);
    return cacheManager;
}

}

そして

@Cacheable(value="A", cacheManager="timeoutCacheManager")
public Object getA(){
...
}

すごい!これはまさに私が探していたものでした
MerLito 2017年

6

これは、org.springframework.cache.interceptor.CacheInterceptorを拡張して「doPut」メソッドをオーバーライドすることで実行できます-org.springframework.cache.interceptor.AbstractCacheInvokerオーバーライドロジックは、キャッシュエントリのTTLを設定することがわかっているキャッシュプロバイダーのputメソッドを使用する必要があります(私の場合、HazelcastCacheManagerを使用します)

@Autowired
@Qualifier(value = "cacheManager")
private CacheManager hazelcastCacheManager;

@Override
protected void doPut(Cache cache, Object key, Object result) {
        //super.doPut(cache, key, result); 
        HazelcastCacheManager hazelcastCacheManager = (HazelcastCacheManager) this.hazelcastCacheManager;
        HazelcastInstance hazelcastInstance = hazelcastCacheManager.getHazelcastInstance();
        IMap<Object, Object> map = hazelcastInstance.getMap("CacheName");
        //set time to leave 18000 secondes
        map.put(key, result, 18000, TimeUnit.SECONDS);



}

キャッシュ構成では、これらの2つのBeanメソッドを追加して、カスタムインターセプターインスタンスを作成する必要があります。

@Bean
public CacheOperationSource cacheOperationSource() {
    return new AnnotationCacheOperationSource();
}


@Primary
@Bean
public CacheInterceptor cacheInterceptor() {
    CacheInterceptor interceptor = new MyCustomCacheInterceptor();
    interceptor.setCacheOperationSources(cacheOperationSource());    
    return interceptor;
}

このソリューションは、TTLをキャッシュレベルではなく、エントリーレベルで設定する場合に適しています。


2

春ブーツ1.3.3以来、あなたが使用してCacheManagerの中の時間を有効期限は設定されてRedisCacheManager.setExpiresまたはRedisCacheManager.setDefaultExpirationをしてCacheManagerCustomizerコールバック豆。


0

Redisを使用する場合、TTLはプロパティファイルで次のように設定できます。

spring.cache.redis.time-to-live=1d # 1 day

spring.cache.redis.time-to-live=5m # 5 minutes

spring.cache.redis.time-to-live=10s # 10 seconds


-2

あなたはRedisのとJava 8で作業している場合、あなたは見てとることができJetCacheを

@Cached(expire = 10, timeUnit = TimeUnit.MINUTES) User getUserById(long userId);


1
質問は春の@Cacheableアノテーションです
satyesht
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.