IT_Programming/Dev Libs & Framework

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

JJun ™ 2015. 7. 9. 00:24



 출처: http://debop.blogspot.kr/2013/03/spring-31-ehcache.html


 참고하기 좋은 자료

    1) 스프링 3.1 Cache Abstraction: http://whiteship.me/?p=13271

    2) spring cache의 적용 (ehcache): http://ironheel.tistory.com/44






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>



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