반응형
캐싱
- java.util.concurrent.ConcurrentMap, Ehcache, Guava, GemFire나 JSR 107(자바 임시 캐싱 API, JCACHE )을 구현한 캐시 솔루션에 대한 캐시 추상화를 즉시지원한다.
- 사용하는 캐시 솔루션이 스프링 캐시 추상화를 지원하지 않는다면, 직접 캐시 솔루션이 제공하는 API를 사용하거나, 스프링이 제공하는 캐시 추상화를 캐시 솔루션에 맞추는 어댑터를 만들어야 한다.
- CacheManager와 Cache 인터페이스는 스프링 캐시 추상화에서 중심적인 역할을 한다.
- CacheManager 인스턴스는 하부 캐시 솔루션이 제공하는 캐시 매니저를 감싸는 래퍼 역할을 하며, Cache 인스턴스의 컬렉션을 관리한다.
- EhCacheManager는 이캐시Ehcache의 net.sf.ehcache.CacheManager를 감싸고, JCacheCacheManager는 JSR 107 프로바이더의 javax.cache.CacheManager를 감싼다.
- Cache 인스턴스는 하부 캐시를 감싸며 하부 캐시와 상호작용하는 메서드를 제공한다.
- EhcacheCache는 net.sf.ehcache.Ehcache의 래퍼고 JCacheCache는 JSR 107 프로바이더의 javax.cache.Cache 인스턴스의 래퍼이다.
- 스프링은 java.util.concurrent.ConcurrentMap을 하부 캐시로 사용하는 ConcurrentMapCacheManager로 제공한다.
- ConcurrentMapCacheManager가 관리하는 Cache 인스턴스는 ConcurrentMapCache다.
- 캐시 솔루션을 위한 CacheManager와 Cache만 직접 구현하면 스프링 캐시에서 해당 솔루션을 사용할 수 있다.
관리한다. <<인터페이스>>
---------------------> Cache
| ^
<<인터페이스>> |
CacheManager ---------------------------------
^ | | |
| EhcacheCache JcacheCache ConcurrentMapCache
|
|
---------------------------------------------------------------------------
| | | |
EhCacheManager JCacheCacheManager SimpleCacheManager ConCurrentMapCacheManager
- CacheManager가 Cache 인스턴스를 관리한다.
- CacheManager 구현은 하부 캐시 솔루션의 캐시 매니저를 둘러싼 래퍼고, Cache 구현은 하부 캐시와 상호작용할 수 있는 연산을 제공한다.
- EhCacheManager는 EhcacheCache 인스턴스를 관리한다.(하부 캐시 저장소는 이캐시)
- JCacheCacheManager는 JcacheCache 인스턴스를 관리한다. (하부 캐시 저장소는 JSR 107을 구현하는 캐시 솔루션)
- ConCurrentMapCacheManager는 ConcurrentMapCache 인스턴스를 관리한다. (하부 캐시 저장소는 java.util.concurrent.ConcurrentMap)
- CacheManager 인터페이스를 구현하는 SimpleCacheManager 클래스로 SimpleCacheManager는 테스트하거나 간단한 캐싱 시나리오를 처리할 때 유용하다.
- java.util.concurrent.ConcurrentMap을 하부 캐시 저장소로 사용하려면, ConcurrentMapCacheManager 대신 SimpleCacheManager를 사용해 캐시를 관리할 수 있다.
CacheManager 설정
<bean id="myCacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
<property name="name" value="fixedDepositList" />
</bean>
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
<property name="name" value="fixedDeposit" />
</bean>
</set>
</property>
</bean>
- SimpleCacheManager의 caches 프로퍼티는 SimpleCacheManager 인스턴스가 관리할 캐시 컬렉션을 지정한다.
- ConcurrentMapCacheFactoryBean을 사용해 ConcurrentMapCache 인스턴스(java.util.concurrent.ConcurrentHashMap 인스턴스를 사용하는 Cache 인스턴스)를 하부 캐시 저장소로 쉽게 설정할 수 있다.
- ConcurrentMapCacheFactoryBean의 name 프로퍼티는 캐시의 이름을 설정한다.
- SimpleCacheManager 인스턴스가 fixedDepositList와 fixedDeposit 캐시를 관리한다.
- 애플리케이션에 적합한 CacheManager를 설정한 후에 스프링 캐시 추상화를 어떻게 사용할지 결정해야 한다.
- 스프링 캐시 수상화를 캐시 애너테이션(@Cacheable, @CacheEvict, @CachePut 등)을 통해 사용할 수 있고, 스프링의 cache 스키마를 통해 사용할 수 있다.
캐시 애너테이션
- 스프링 cache 스키마의 <annotation-driven> 엘리먼트를 설정한다.
<cache:annotation-driven cache-manager="myCacheManager"/>
- cache-manager 속성은 캐시를 관리하는 CacheManager 빈을 가리킨다.
- CacheManager 빈 이름이 cacheManager라면 cache-manager 속성을 지정하지 않아도 된다.
- 자바 기반 설정시에 @EnableCaching 사용해 캐시 애너테이션을 활성화 한다.
@Cacheable
- 메서드에 @Cacheable 설정하면 메서드의 반환값을 캐시에 넣는다
- @Cacheable의 key 속성은 반환한 값을 캐시에 저장할 때 사용할 키를 지정한다.
- key 속성을 지정하지 않으면 디폴트로 스프링 SimpleKeyGenerator 클래스를 사용해 메서드가 반환한 값을 캐시에 저장할 때 사용할 키를 생성한다.
- SimpleKeyGenerator는 메서드 시그니처와 인수를 사용해 키를 계산한다.
- <annotation-driven>의 key-generator 속성을 사용하면 디폴트 키 생성기를 커스텀 key Generator 구현으로 바꿀 수 있다.
@Cacheable(cacheNames = { "fixedDepositList" })
public List<FixedDepositDetails> findFixedDepositsByBankAccount(int bankAccountId) {
logger.info("findFixedDepositsByBankAccount method invoked");
return myFixedDepositDao.findFixedDepositsByBankAccount(bankAccountId);
}
- @Cacheable 애너테이션의 cacheNames 속성은 반환값을 캐시할 캐시 영역을 지정한다.
- MyBank 애플리케이션을 위해 fixedDepositList 캐시 영역을 만든다.
- @Cacheable은 findFixedDepositsByBankAccount 메서드가 반환하는 값을 fixedDepositList 캐시에 저장한다.
- key 속성을 지정하지 않아서 SimpleKeyGenerator는 메서드 인수인 bankAccountId 값을 키로 사용한다.
- @Cacheable을 설정한 메서드가 호출되면 설정된 KeyGenerator가 키를 계산한다.
- 키가 캐시에 이미 들어 있으면 @Cacheable 메서드가 호출되지 않는다.
- 키가 캐시에 들어 있지 않으면, @Cacheable 메서드가 호출되고 반환값을 계산한 키를 사용해 캐시에 넣느낟.
- SimpleKeyGenerator를 키 생성기로 사용하는 경움, 메서드에 전달한 인수가 모두 같을 때 @Cacheable을 설정한 메서드를 호출하지 않는다.
- 하지만 인수 중 단 하나라도 다른 값을 사용하면 @Cacheable을 설정한 메서드가 호출된다.
@CacheEvict
- 어떤 메서드가 호출되면 캐시에 잇는 데이터를 모두 비울 때 @CacheEvict를 설정한다.
- 새로운 정기 예금이 생성되면 FixedDepositServiceImpl의 findFixedDepositByBankAccount 메서드에 의해 저장된 정기 예금 정보를 반드시 캐시에서 제거해야 한다.
- 그래야 다음에 findFixedDepositByBankAccount 메서드가 호출될 때 새로 만든 정기 예금 정보를 데이터베이스에 가져올 수 있다.
@Override
@Transactional(transactionManager = "jmsTxManager")
@CacheEvict(cacheNames = { "fixedDepositList" }, allEntries = true, beforeInvocation = true)
public void createFixedDeposit(final FixedDepositDetails fdd) throws Exception {
logger.info("createFixedDeposit method invoked");
jmsTemplate.send("emailQueueDestination", new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage();
textMessage.setText(fdd.getEmail());
return textMessage;
}
});
// --this JMS message goes to the default destination configured for the
// JmsTemplate
jmsTemplate.send(new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
ObjectMessage objectMessage = session.createObjectMessage();
objectMessage.setObject(fdd);
return objectMessage;
}
});
jmsTemplate.convertAndSend("aDestination", "Hello world", new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws JMSException {
message.setBooleanProperty("printOnConsole", true);
return message;
}
});
}
- createFixedDeposit 메서드에서 @CacheEvict는 스프링이 fixedDepositList 캐시 영역에서 모든 캐시 엔트리를 지우도록 지시한다.
- cacheNames 속서은 캐시 원소를 없앨 캐시영역을 지정하며, allEntries 속성은 지정한 캐시 영역에서 모든 엔트리를 비울지, 일부만 비울지 결정한다.
- 특정 캐시 아이템을 캐시에 비운다면 key 속성을 사용해 아이템을 저장할 때 사용한 키를 지정한다.
- 또한 condition 속서을 사용하면 조건에 따라 아이템을 비울 수도 있다.
- condition과 key 속성은 SpEL을 사용해 값을 지정하도록 허용한다. 복잡한 조건을 적용해서 캐시를 비울 수 있다.
- beforeInvocation은 캐시를 메서드 실행 이전이나 이후 중 언제 비울지 결정한다.
- beforeInvocation 속성의 값이 true이므로 createFixedDeposit 메서드를 호출하기 전에 캐시를 비운다.
@CachePut
- 스프링은 추가로 항상 메서드를 호출해서 반환값을 캐시에 넣어야 한다는 의미로 @CachePut 애너테이션을 지원한다.
- @CachePut은 스프링에게 캐시에 키가 이미 있는 경우 메서드를 호출하지 말라고 지시하는 @Cacheable과 다르다.
@Override
@CachePut(cacheNames = { "fixedDeposit" }, key = "#fixedDepositId")
public FixedDepositDetails getFixedDeposit(int fixedDepositId) {
logger.info("getFixedDeposit method invoked with fixedDepositId " + fixedDepositId);
return myFixedDepositDao.getFixedDeposit(fixedDepositId);
}
@Override
@Cacheable(cacheNames = { "fixedDeposit" }, key = "#fixedDepositId")
public FixedDepositDetails getFixedDepositFromCache(int fixedDepositId) {
logger.info("getFixedDepositFromCache method invoked with fixedDepositId " + fixedDepositId);
throw new RuntimeException(
"This method throws exception because FixedDepositDetails object must come from the cache");
}
- @CachePut은 getFixedDeposit 메서드에 설정한다.
- getFixedDeposit 메서드가 항상 호출되고, 메서드가 반환하는 FixedDepositDetails 객체가 fixedDeposit 캐시에 저장된다.
- cacheNames은 반환된 FixedDepositDetails를 저장할 때 캐시 이름을 지정한다.
- key 속성은 반환된 FixedDepositDetails 객체를 저장할 때 사용할 키를 지정한다.
- key 속성은 키를 지정하기 위해 SpEL을 사용한다.
- key 속성값인 #fixedDepositId는 getFixedDeposit 메서드에 전달된 fixedDepositId 인수를 가리킨다.
- getFixedDeposit 메서드가 반환하는 FixedDepositDetails 객체를 fixedDeposit 캐시에 저장할 때 메서드 인수인 fixedDepositId 값을 키로 쓴다.
- getFixedDepositFromCache 메서드는 @Cacheable을 지정한 key 속성값에 따라 캐시에 FixedDepositDetails 객체를 읽는다.
- getFixedDepositFromCache 메서드는는 단시 RuntimeException을 던지기만 한다.
- key 속성은 getFixedDepositFromCache 메서드에 전달된 fixedDepositId 인수를 가리킨다.
- FixedDepositDetails 객체를 캐시에서 찾지 못하면 getFixedDepositFromCache가 호출되고, 이때 RuntimeException이 발생한다.
스프링 cache 스키마를 사용해 캐시 설정
- 애너테이션 대신 cache 스키마를 사용해 애플리케이션 캐시를 설정할 수 있따.
<cache:advice id="cacheAdvice" cache-manager="myCacheManager">
<cache:caching cache="fixedDepositList">
<cache:cache-evict method="createFixedDeposit"
all-entries="true" before-invocation="true" />
<cache:cacheable method="findFixedDepositsByBankAccount" />
</cache:caching>
<cache:caching cache="fixedDeposit">
<cache:cache-put method="getFixedDeposit" key="#fixedDepositId" />
<cache:cacheable method="getFixedDepositFromCache"
key="#fixedDepositId" />
</cache:caching>
</cache:advice>
<aop:config>
<aop:advisor advice-ref="cacheAdvice"
pointcut="execution(* sample.spring.chapter10.bankapp.service.FixedDepositService.*(..))" />
</aop:config>
- <advice>의 cache-manager 속성은 캐시를 관리할 때 사용할 CacheManager 빈을 지정한다.
- <caching>의 cache 속성이 지정한 캐시 영역의 캐시 동작을 설명한다.
- <cache-evict>, <cache-put>, <cacheable> 순서대로 @CacheEvict, @CachePup, @Cacheable에 해당한다.
- aop 스키마의 config 엘리먼트를 사용해 정의한 캐시 동작을 FixedDepositService 인터페이스가 정의한 메서드에 적용한다.
- <advisor>의 advice-ref 속성은 캐시 동작을 정의하는 <advisor>를 참조하고 pointcut 속성은 캐시 동작을 적용할 메시지를 지정한다.
배워서 바로 쓰는 스프링프레임워크
애시시 사린, 제이 샤르마 지음
오현석 옮김
반응형
'JAVA > Spring' 카테고리의 다른 글
검증과 데이터바인딩 (0) | 2022.01.28 |
---|---|
AOP (0) | 2022.01.28 |
데이터베이스 연결 (0) | 2022.01.05 |
빈과 빈 정의 커스텀 (0) | 2021.12.26 |
의존관계주입 (0) | 2021.12.26 |