javascript
spring 请求转码_Spring请求级备忘录
spring 請求轉碼
介紹
備注化是一種方法級別的緩存技術,用于加快連續調用的速度。
這篇文章將演示如何僅使用Spring AOP實現任何數據源的請求級可重復讀取。
Spring緩存
Spring提供了非常有用的緩存抽象 ,允許您將應用程序邏輯與緩存實現細節分離。
Spring Caching使用應用程序級范圍,因此對于僅請求的備忘錄,我們需要采用DIY方法。
請求級緩存
請求級緩存條目生命周期始終綁定到當前請求范圍。 這樣的緩存與提供會話級可重復讀取的 Hibernate Persistence Context非常相似。
為了防止更新丟失 ,甚至對于NoSQL解決方案,必須進行可重復的讀取 。
分步實施
首先,我們將定義一個“記憶標記”注釋:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Memoize { }該注釋將顯式標記所有需要記住的方法。
為了區分不同的方法調用,我們將方法調用信息封裝為以下對象類型:
public class InvocationContext {public static final String TEMPLATE = "%s.%s(%s)";private final Class targetClass;private final String targetMethod;private final Object[] args;public InvocationContext(Class targetClass, String targetMethod, Object[] args) {this.targetClass = targetClass;this.targetMethod = targetMethod;this.args = args;}public Class getTargetClass() {return targetClass;}public String getTargetMethod() {return targetMethod;}public Object[] getArgs() {return args;}@Overridepublic boolean equals(Object that) {return EqualsBuilder.reflectionEquals(this, that);}@Overridepublic int hashCode() {return HashCodeBuilder.reflectionHashCode(this);}@Overridepublic String toString() {return String.format(TEMPLATE, targetClass.getName(), targetMethod, Arrays.toString(args));} }很少有人知道Spring Request / Session bean的作用域。
因為我們需要一個請求級的備忘錄作用域,所以我們可以使用Spring請求范圍來簡化我們的設計,該作用域隱藏了實際的HttpSession解析邏輯:
@Component @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "request") public class RequestScopeCache {public static final Object NONE = new Object();private final Map<InvocationContext, Object> cache = new HashMap<InvocationContext, Object>();public Object get(InvocationContext invocationContext) {return cache.containsKey(invocationContext) ? cache.get(invocationContext) : NONE;}public void put(InvocationContext methodInvocation, Object result) {cache.put(methodInvocation, result);} }由于沒有運行時處理引擎,僅注釋就沒有任何意義,因此,我們必須定義一個實現實際備注邏輯的Spring Aspect:
@Aspect public class MemoizerAspect {@Autowiredprivate RequestScopeCache requestScopeCache;@Around("@annotation(com.vladmihalcea.cache.Memoize)")public Object memoize(ProceedingJoinPoint pjp) throws Throwable {InvocationContext invocationContext = new InvocationContext(pjp.getSignature().getDeclaringType(),pjp.getSignature().getName(),pjp.getArgs());Object result = requestScopeCache.get(invocationContext);if (RequestScopeCache.NONE == result) {result = pjp.proceed();LOGGER.info("Memoizing result {}, for method invocation: {}", result, invocationContext);requestScopeCache.put(invocationContext, result);} else {LOGGER.info("Using memoized result: {}, for method invocation: {}", result, invocationContext);}return result;} }測試時間
讓我們對所有這些進行測試。 為簡單起見,我們將使用Fibonacci數字計算器模擬請求級范圍的備忘需求:
@Component public class FibonacciServiceImpl implements FibonacciService {@Autowiredprivate ApplicationContext applicationContext;private FibonacciService fibonacciService;@PostConstructprivate void init() {fibonacciService = applicationContext.getBean(FibonacciService.class);}@Memoizepublic int compute(int i) {LOGGER.info("Calculate fibonacci for number {}", i);if (i == 0 || i == 1)return i;return fibonacciService.compute(i - 2) + fibonacciService.compute(i - 1);} }如果要計算第十個斐波那契數,我們將得到以下結果:
Calculate fibonacci for number 10 Calculate fibonacci for number 8 Calculate fibonacci for number 6 Calculate fibonacci for number 4 Calculate fibonacci for number 2 Calculate fibonacci for number 0 Memoizing result 0, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([0]) Calculate fibonacci for number 1 Memoizing result 1, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([1]) Memoizing result 1, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([2]) Calculate fibonacci for number 3 Using memoized result: 1, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([1]) Using memoized result: 1, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([2]) Memoizing result 2, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([3]) Memoizing result 3, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([4]) Calculate fibonacci for number 5 Using memoized result: 2, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([3]) Using memoized result: 3, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([4]) Memoizing result 5, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([5]) Memoizing result 8, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([6]) Calculate fibonacci for number 7 Using memoized result: 5, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([5]) Using memoized result: 8, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([6]) Memoizing result 13, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([7]) Memoizing result 21, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([8]) Calculate fibonacci for number 9 Using memoized result: 13, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([7]) Using memoized result: 21, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([8]) Memoizing result 34, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([9]) Memoizing result 55, for method invocation: com.vladmihalcea.cache.FibonacciService.compute([10])結論
記憶是一個貫穿各領域的問題,Spring AOP允許您將緩存詳細信息與實際的應用程序邏輯代碼分離。
- 代碼可在GitHub上獲得 。
翻譯自: https://www.javacodegeeks.com/2014/12/spring-request-level-memoization.html
spring 請求轉碼
總結
以上是生活随笔為你收集整理的spring 请求转码_Spring请求级备忘录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样看电脑硬盘模式(怎么看硬盘模式)
- 下一篇: java处理注释_如何处理Java注释