BAEL-6300: Invoking Spring Cache @Cacheable from Another Method of the Same Bean (#14689)

* BAEL-6300: Problem Reproduction

* BAEL-6300: Internal Invocation with External Reference

* BAEL-6300: compile-time weaving

* BAEL-6300: load-time weaving
This commit is contained in:
Forb Yuan
2023-09-02 22:23:29 +08:00
committed by GitHub
parent 29c9c5dba9
commit 8c3d581fa9
9 changed files with 300 additions and 0 deletions
@@ -2,8 +2,16 @@ package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
@SpringBootApplication
@ComponentScan(basePackages = { "com.baeldung" }, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,
value = { SpringBootApplication.class})
})
@EnableCaching
public class Application {
public static void main(String[] args) {
@@ -0,0 +1,20 @@
package com.baeldung.selfinvocation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
@SpringBootApplication
@EnableCaching(mode = AdviceMode.ASPECTJ)
@ComponentScan(basePackages = { "com.baeldung" }, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,
value = { SpringBootApplication.class})
})
public class CompileTimeWeavingApplication {
public static void main(String[] args) {
SpringApplication.run(CompileTimeWeavingApplication.class, args);
}
}
@@ -0,0 +1,16 @@
package com.baeldung.selfinvocation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
@SpringBootApplication
@EnableCaching(mode = AdviceMode.ASPECTJ)
@EnableLoadTimeWeaving
public class LoadTimeWeavingApplication {
public static void main(String[] args) {
SpringApplication.run(LoadTimeWeavingApplication.class, args);
}
}
@@ -0,0 +1,43 @@
package com.baeldung.selfinvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;
@Service
@CacheConfig(cacheNames = "square")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MathService {
@Autowired
private MathService self;
private final AtomicInteger counter = new AtomicInteger();
@CacheEvict(allEntries = true)
public AtomicInteger resetCounter() {
counter.set(0);
return counter;
}
@Cacheable(key = "#n")
public double square(double n) {
counter.incrementAndGet();
return n * n;
}
public double sumOfSquareOf2() {
return this.square(2) + this.square(2);
}
public double sumOfSquareOf3() {
return self.square(3) + self.square(3);
}
}
@@ -17,6 +17,8 @@
<logger name="org.springframework.aop.interceptor.PerformanceMonitorInterceptor" level="TRACE" />
<logger name="org.aspectj.weaver" level="WARN" />
<root level="TRACE">
<appender-ref ref="STDOUT" />
</root>
@@ -0,0 +1,24 @@
package com.baeldung.selfinvocation;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = CompileTimeWeavingApplication.class)
class CompileTimeWeavingIntegrationTest {
@Resource
private MathService mathService;
@Test
void givenCacheableMethod_whenInvokingByInternalCall_thenCacheIsTriggered() {
AtomicInteger counter = mathService.resetCounter();
assertThat(mathService.sumOfSquareOf2()).isEqualTo(8);
assertThat(counter.get()).isEqualTo(1);
}
}
@@ -0,0 +1,25 @@
package com.baeldung.selfinvocation;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = LoadTimeWeavingApplication.class)
class LoadTimeWeavingIntegrationTest {
@Resource
private MathService mathService;
@Test
void givenCacheableMethod_whenInvokingByInternalCall_thenCacheIsTriggered() {
AtomicInteger counter = mathService.resetCounter();
assertThat(mathService.sumOfSquareOf2()).isEqualTo(8);
assertThat(counter.get()).isEqualTo(1);
}
}
@@ -0,0 +1,47 @@
package com.baeldung.selfinvocation;
import com.baeldung.Application;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = Application.class)
class MathServiceIntegrationTest {
@Resource
private MathService mathService;
@Test
void givenCacheableMethod_whenInvokedForSecondTime_thenCounterShouldNotIncrease() {
AtomicInteger counter = mathService.resetCounter();
assertThat(mathService.square(2)).isEqualTo(4);
assertThat(counter.get()).isEqualTo(1);
mathService.square(2);
assertThat(counter.get()).isEqualTo(1);
mathService.square(3);
assertThat(counter.get()).isEqualTo(2);
}
@Test
void givenCacheableMethod_whenInvokingByInternalCall_thenCacheIsNotTriggered() {
AtomicInteger counter = mathService.resetCounter();
assertThat(mathService.sumOfSquareOf2()).isEqualTo(8);
assertThat(counter.get()).isEqualTo(2);
}
@Test
void givenCacheableMethod_whenInvokingByExternalCall_thenCacheIsTriggered() {
AtomicInteger counter = mathService.resetCounter();
assertThat(mathService.sumOfSquareOf3()).isEqualTo(18);
assertThat(counter.get()).isEqualTo(1);
}
}