Pyohwan / english-study

0 stars 0 forks source link

Spring Framework Documentation : Integration (8) #26

Open Pyohwan opened 4 years ago

Pyohwan commented 4 years ago

8. Cache Abstraction

캐시 추상화는 멀티스레드 및 멀티프로세스에 대한 특별한 처리가 없다. 이러한 기능은 캐시 구현으로 처리 된다

8.2. Declarative Annotation-based Caching

8.2.1. The @Cacheable Annotation

default key generation 전략이 Spring 4.0 부터 바뀌었는데, 이전에는 equals() 를 안보고 hashCode() 만 고려 했음. 이거는 key 충돌이 발생할 수도 있기때문에, 새로운 SimpleKeyGenerator 는 복합키를 사용 함

Custom Key Generation Declaration

@Cacheable(cacheNames="books", key="#isbn.rawNumber") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

*  커스텀 `keyGenerator` 적용 가능

@Cacheable(cacheNames="books", keyGenerator="myKeyGenerator") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)


> key 와 keyGenerator 파라미터는 서로 배타적이라 둘중에 하나만 해야 함. 그렇게 안하면 exceptioun 발생

##### Default Cache Resolution
* 캐시 추상화는 `CacheResolver` 로, 구성된 `CacheManager` 를 사용하여 캐시를 검색 함
* 다른 캐시 resolver 를 쓸려면, `org.springframework.cache.interceptor.CacheResolver` 를 구현해라

##### Custom Cache Resolution
* 기본 캐시 resolution 은 single `CacheManager` 에서 동작하고, 복잡하지 않는 요구사항에 적합 함
* 여러 캐시 매니저가 있을 경우, `cacheManager` 를 설정해서 아래처럼 조작 가능하다

@Cacheable(cacheNames="books", cacheManager="anotherCacheManager") public Book findBook(ISBN isbn) {...}

* `CacheResolver` 도 대체 가능 함

@Cacheable(cacheResolver="runtimeCacheResolver") public Book findBook(ISBN isbn) {...}


> Spring 4.1 부터 `value` 는 더이상 필수가 아님. `CacheResolver` 정보를 제공 가능하기 때문임
> cacheManager 와 cacheResolver 파라미터는 상호 배타적임. 둘중에 하나만 써야 함

##### Synchronized Caching
* 멀티 쓰레드 환경에서 동일한 파라미터로 동시에 호출 될 수 있다. 기본적으로 캐시 추상화는 lock 을 하지 않기 때문에 동일한 값이 여러번 계산될 수 있다
* 이렬 경우 `sync` 애트리뷰트로 lock 설정이 가능하다. 결국 하나의 쓰레드에서만 값을 계산하고, 다른 쓰레드에서는 차단 됨

@Cacheable(cacheNames="foos", sync=true) public Foo executeExpensiveOperation(String id) {...}


##### Conditional Caching
* 때로는 주어진 아규먼트에 따라 캐싱이 결정날 수 도 있다.
* `condition` 파라미터로 SpEL 표현 가능 함.
* 다음 예제는 아구먼트 길이가 32보다 짧은 경우에만 캐시 함

@Cacheable(cacheNames="book", condition="#name.length() < 32") public Book findBook(String name)

* `unless` 파라미터로 캐시 거부 가능하다. 하지만 `condition` 과는 다르게 `unless` 는 메소드 수행 이후에 평가 된다
* 다음의 예제는 paperback 일때에만 캐싱 하도록 확장 했다

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback") public Book findBook(String name)

* `java.util.Optional` 도 지원 가능하며 값이 주어진 경우에만 캐싱 함. 

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result?.hardback") public Optional findBook(String name)


##### Available Caching SpEL Evaluation Context
* [문서](https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/integration.html#cache-spel-context) 참고

#### 8.2.2. The @CachePut Annotation
* 메소드 실행을 방해하지 않고, 캐시 업데이트 가능 `@CachePut`
* `@Cacheable` 와 동일한 옵션 제공

@CachePut(cacheNames="book", key="#isbn") public Book updateBook(ISBN isbn, BookDescriptor descriptor)


> 동일한 메소드에서 @CachePut and @Cacheable 둘다 사용하는건 권장하지 않음.  후자는 캐시를 사용하여 메소드 실행을 안하지만, 전자는 캐시 업데이트를 위해 실행 됨.

#### 8.2.3. The @CacheEvict annotation
* books 의 모든 캐시 제거

@CacheEvict(cacheNames="books", allEntries=true) public void loadBooks(InputStream batch)

* `beforeInvocation` 애트리뷰트로 메소드 실행 이전 or 이후(default) 에 캐시 제거 하도록 설정 가능 함. 

#### 8.2.4. The @Caching Annotation
* 때로는 동일한 타입의 멀티플 애너테이션을 적용 해야 한다 (such as @CacheEvict or @CachePut)

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") }) public Book importBooks(String deposit, Date date)

#### 8.2.5. The @CacheConfig annotation
* 각 메소드마다 캐싱 설정 하기 번거로우니, 클래스 레벨에서 공통으로 캐싱 설정 적용 가능한 `@CacheConfig` 있음
* 캐시 name 을 지정 함

@CacheConfig("books") public class BookRepositoryImpl implements BookRepository {

@Cacheable
public Book findBook(ISBN isbn) {...}

}

* operation-level customization (메소드인듯?) 는 `@CacheConfig` 보다 우선 함

#### 8.2.6. Enabling Caching Annotations
* `@EnableCaching` 붙히면 캐싱 자동 구성 됨

> 세부적으로 구성 하고 싶다면 `CachingConfigurer` 구현 하라. [javadoc](https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/cache/annotation/CachingConfigurer.html) 참고

> default 캐싱 애너테이션 advice 모드는 `proxy` 임
> 같은 클래스에서 Local 호출시에는 인터셉트가 안됨. compile-time or load-time  에 엮을려면 `aspectj` 모드 전환해라

* Cache annotation settings [참고](https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/integration.html#cache-annotation-enable)

> proxy 를 쓸려면 public 메소드에 캐시 애너테이션 쓸수 있다. 

> Spring 은 인터페이스에 `@Cache*` 를 붙히지 말고, 클래스에 붙히길 권한다. 

#### 8.2.7. Using Custom Annotations
* 필요할때 보자. 생략
### 8.3. JCache (JSR-107) Annotations
* 필요할때 보자. 생략
### 8.4. Declarative XML-based Caching
* 안봐도 됨
### 8.5. Configuring the Cache Storage
#### 8.5.1. JDK ConcurrentMap-based Cache
* ConcurrentHashMap 를 사용하는 Cache store
* 캐시는 애플리케이션에서 생성되기 때문에 기본적인 사용 예제, 테스트, 간단한 애플리케이션에 적합하다. 
* 확장성이 좋고 매우 빠르지만, 관리 방법, persistence capabilities, eviction contracts 제공 안함
#### 8.5.2. Ehcache-based Cache
> Ehcache 3.x 은 JSR-107 와 완벽히 호환됨
* Ehcache 2.x implementation 은 `org.springframework.cache.ehcache` 패키지에 있음. 또한 `CacheManager` declare  필요

#### 8.5.3. Caffeine Cache
* Guava 캐시를 Java 8 로 재작성 한것임
* `CacheManager` 는 커스텀 Caffeine and CacheLoader 를 지원 함
  * [caffeine 문서](https://github.com/ben-manes/caffeine/wiki) 참고

#### 8.5.4. GemFire-based Cache
* memory-oriented, disk-backed, elastically scalable, continuously available

#### 8.5.5. JSR-107 Cache
* JSR-107 호환 캐시 사용 가능 

#### 8.5.6. Dealing with Caches without a Backing Store
* 실제 백업 캐시 없이 구성할 경우가 있는데, 에러를 방지하는 더미 캐시를 만듦
  * 이럴 경우, 해당 메소드는 캐싱 되지 않고 계속 실행

* `CompositeCacheManager` 는 멀티플 `CacheManager` 인스턴스를 가졌는데, `fallbackToNoOpCache` flag 를 통해서, 비작동 캐시를 넣을 수 있음

### 8.6. Plugging-in Different Back-end Caches
* 배킹 스토어로 사용할 캐시 제품은 많다. CacheManager 가 없는경우 직접 구현 해야 한다.
Pyohwan commented 4 years ago

https://github.com/ben-manes/caffeine/wiki

Caffeine