2013년 3월 24일 일요일

Spring 3.1 + EhCache 를 이용하여 캐시 사용하기

Spring 3.1 이상부터 Annotation을 이용하여, Cache 를 아주 쉽게 사용할 수 있습니다.
데이터를 처리하는 함수에서 @Cacheable 이라는 annotation을 사용하여, 반환되는 데이터를 캐시에 저장한다고 지정하기만 하면 됩니다.

Spring 3.1 Caching and @Cacheable 와 같은 좋은 예제가 많으니 그걸 참고하셔도 됩니다.

저도 비슷하게 함 예제를 만들어 봤습니다.
우선 캐시할 정보를 관리하는 UserRepository 라는 클래스를 구현했습니다. 보시다시피 @Repository 입니다.

@Repository
@Slf4j
public class UserRepository {
@Cacheable(value = "user", key = "#id")
public User getUser(String id) {
return getUser(id, 1000);
}
@Cacheable(value = "user", key = "#id")
public User getUser(String id, int favoriteMovieSize) {
User user = new User();
user.setUsername(id);
user.setPassword(id);
user.setEmail("sunghyouk.bae@gmail.com");
user.getHomeAddress().setPhone("999-9999");
user.getOfficeAddress().setPhone("555-5555");
for (int i = 0; i < favoriteMovieSize; i++)
user.getFavoriteMovies().add("Favorite Movie Number-" + i);
if (UserRepository.log.isDebugEnabled())
UserRepository.log.debug("Create User...");
return user;
}
}



처음 getUser() 메소드를 호출하게 되면,  User 인스턴스가 생성되어 반환되면서, 캐시에 자동 저장되고, 두번째 호출서부터는 캐시로부터 읽어드립니다.

정말 편하죠? Cache 와 관련된 코드가 설정만으로 끝낼 수 있다니^^ 물론 Cache 무효화나 key에 따라 다른 결과는 다른 키로 저장하기, 조건에 따라 캐싱하기 등등 더 많은 기능이 있습니다.

위와 같이 Cache 사용하기 위해서는 다음과 같이 Spring Configuration 을 정의합니다.

@Configuration
@EnableCaching
@ComponentScan(basePackageClasses = {UserRepository.class})
@Slf4j
public class EhcacheConfiguration {
@Bean(name = "ehcache")
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
bean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return bean;
}
@Bean(name = "cacheManager")
public EhCacheCacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());
}
@PostConstruct
public void postConstruct() {
EhcacheConfiguration.log.info("Cache Created");
}
}

보시다시피, EhCacheCacheManager 를 제공하는 Bean이 실제 쓰이는 CacheManager 입니다.

테스트는 Spring Configuration을 지정하고, UserRepository.getUser() 를 같은 값으로 두 번 호출하여, 두 번째가 캐시에서 읽어오는지 확인하면 됩니다.
(UserRepository에 보면 log에 쓰는 부분이 있죠? 두 번째에는 나타나지 않으면 됩니다.)

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {EhcacheConfiguration.class})
public class EhcacheTest {
@Autowired
EhCacheCacheManager cacheManager;
@Autowired
UserRepository userRepository;
@Test
public void getUserFromCache() {
Stopwatch sw = new Stopwatch("initial User");
sw.start();
User user1 = userRepository.getUser("debop", 100);
sw.stop();
sw = new Stopwatch("from Cache");
sw.start();
User user2 = userRepository.getUser("debop", 100);
sw.stop();
Assert.assertEquals(user1, user2);
}
}

자 테스트 코드는 위와 같고, 마지막으로 ehcache  설정은 다음과 같습니다.

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
updateCheck="false" monitoring="autodetect" dynamicConfig="false"
maxBytesLocalHeap="75%" name="debop4j-cache">
<diskStore path="java.io.tmpdir"/>
<cache name="user"
eternal="true"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"
statistics="false"
/>
</ehcache>
view raw ehcache.xml hosted with ❤ by GitHub


이 것을 응용해서 다른 Cache Provider 에 대해서도 작업을 하실 수 있을 것입니다. 요즘 가장 성능 좋은 것으로 사용되는 Redis 를 활용해도 되겠지요^^

댓글 없음: