Add caching: the Spring cache abstraction, keys, eviction timing and the self-invocation trap
A Spring Boot 4.1.1 module whose test suite is the evidence for the article: 19 tests producing 22 transcripts under docs/output/, plus 12 documentation chapters. Findings the build pins: - @EnableCaching has no exposeProxy attribute; the widely-copied @EnableCaching(exposeProxy = true) does not compile. - Two methods sharing a cache name and an argument type share a key space, and one silently serves the other's answers. - beforeInvocation = true is NOT deferred by TransactionAwareCacheManagerProxy on 7.0.9 - doEvict picks evictIfPresent, which the decorator does not intercept. - Four of five invalid declarations start a clean context and throw at the first call. - Caffeine on the classpath silently displaces the simple provider.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# Why beforeInvocation=true is not deferred by TransactionAwareCacheManagerProxy
|
||||
|
||||
$ javap -c -p org.springframework.cache.interceptor.AbstractCacheInvoker # spring-context-7.0.9.jar
|
||||
protected void doEvict(org.springframework.cache.Cache, java.lang.Object, boolean);
|
||||
Code:
|
||||
0: iload_3
|
||||
1: ifeq 15
|
||||
4: aload_1
|
||||
5: aload_2
|
||||
6: invokeinterface #83, 2 // InterfaceMethod org/springframework/cache/Cache.evictIfPresent:(Ljava/lang/Object;)Z
|
||||
11: pop
|
||||
12: goto 22
|
||||
15: aload_1
|
||||
16: aload_2
|
||||
17: invokeinterface #87, 2 // InterfaceMethod org/springframework/cache/Cache.evict:(Ljava/lang/Object;)V
|
||||
22: goto 40
|
||||
25: astore 4
|
||||
|
||||
$ javap -c -p org.springframework.cache.transaction.TransactionAwareCacheDecorator # spring-context-support-7.0.9.jar
|
||||
public void evict(java.lang.Object);
|
||||
Code:
|
||||
0: invokestatic #48 // Method org/springframework/transaction/support/TransactionSynchronizationManager.isSynchronizationActive:()Z
|
||||
3: ifeq 21
|
||||
6: new #71 // class org/springframework/cache/transaction/TransactionAwareCacheDecorator$2
|
||||
9: dup
|
||||
10: aload_0
|
||||
11: aload_1
|
||||
12: invokespecial #73 // Method org/springframework/cache/transaction/TransactionAwareCacheDecorator$2."<init>":(Lorg/springframework/cache/transaction/TransactionAwareCacheDecorator;Ljava/lang/Object;)V
|
||||
15: invokestatic #59 // Method org/springframework/transaction/support/TransactionSynchronizationManager.registerSynchronization:(Lorg/springframework/transaction/support/TransactionSynchronization;)V
|
||||
18: goto 31
|
||||
21: aload_0
|
||||
22: getfield #15 // Field targetCache:Lorg/springframework/cache/Cache;
|
||||
25: aload_1
|
||||
public boolean evictIfPresent(java.lang.Object);
|
||||
Code:
|
||||
0: aload_0
|
||||
1: getfield #15 // Field targetCache:Lorg/springframework/cache/Cache;
|
||||
4: aload_1
|
||||
5: invokeinterface #80, 2 // InterfaceMethod org/springframework/cache/Cache.evictIfPresent:(Ljava/lang/Object;)Z
|
||||
10: ireturn
|
||||
|
||||
|
||||
doEvict(cache, key, true) -> Cache.evictIfPresent -> straight to the target cache
|
||||
doEvict(cache, key, false) -> Cache.evict -> registerSynchronization, runs after commit
|
||||
|
||||
spring-framework#23192 reported beforeInvocation=true being swallowed by the
|
||||
transaction-aware decorator. On 7.0.9 it is not: the immediate path uses a method
|
||||
the decorator does not intercept. Note also that the decorator ships in
|
||||
spring-context-support, not spring-context.
|
||||
Reference in New Issue
Block a user