Use Guava Cache To Improve Performance

  • Posted on: 18 April 2015
  • By: Zhijun Chen

It is quite often that you might want to use cache a value when it is expensive to compute or retrieve, e.g. involves several hibernate queries and serialization.

Guava Cache is one of the options if you just need to cache the value in RAM instead of files.

In my case, I'm using CacheLoader as I've got key/value pairs. The following utility class shows how this can be done.

package uk.co.zhijun.manager.cache;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

/**
 * 
 */
public class StudentCache {

  private static Logger logger = LoggerFactory
      .getLogger(StudentCache.class);

  private LoadingCache<Long, Student> studentCache;
  private StudentManager studentManager;

  public StudentCache(int expirationTimeMinutes) {
    buildStudentCache(expirationTimeMinutes);
  }

  private void buildStudentCache(int expirationTimeMinutes) {
    studentCache = CacheBuilder.newBuilder()
        .expireAfterAccess(expirationTimeMinutes, TimeUnit.MINUTES)
        .removalListener(studentRemovalListener)
        .build(new CacheLoader<Long, Student>() {

          @Override
          public Student load(Long id) throws Exception {
            return studentManager.getStudentById(id);
          }
        });
  }

  public Student getStudent(Long id) throws ExecutionException {
      return studentCache.get(id);
  }

  public void invalidateStudentCache(Long id) {
    studentCache.invalidate(id);
  }

  private RemovalListener<Long, Student> studentRemovalListener = new RemovalListener<Long, Student>() {
    public void onRemoval(RemovalNotification<Long, Student> removal) {
      logger.info(
          "Refreshing student, studentId = {}, was evicted? {}",
          removal.getKey(), removal.wasEvicted());
    }
  };

  /* provided for spring setter injection */
  public void setStudentManager(StudentManager studentManager) {
    this.studentManager = studentManager;
  }
}

You can then register this class in the spring context and use it. The cache should be evicted everytime a change is going to affect the Student object.

...
<bean id="studentCache" class="uk.co.zhijun.manager.cache.StudentCache">
  <constructor-arg name="expirationTimeMinutes" value="10" />
  <property name="studentManager" ref="studentManager" />
</bean>
...

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.