Polish "Evaluate key only if necessary"
See gh-22769
This commit is contained in:
@@ -119,10 +119,6 @@ public @interface CacheEvict {
|
|||||||
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
||||||
* following meta-data:
|
* following meta-data:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code #result} for a reference to the result of the method invocation, which
|
|
||||||
* can only be used if {@link #beforeInvocation()} is {@code false}. For supported
|
|
||||||
* wrappers such as {@code Optional}, {@code #result} refers to the actual object,
|
|
||||||
* not the wrapper</li>
|
|
||||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||||
* affected cache(s) respectively.</li>
|
* affected cache(s) respectively.</li>
|
||||||
|
|||||||
@@ -131,9 +131,6 @@ public @interface Cacheable {
|
|||||||
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
* <p>The SpEL expression evaluates against a dedicated context that provides the
|
||||||
* following meta-data:
|
* following meta-data:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code #result} for a reference to the result of the method invocation. For
|
|
||||||
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
|
|
||||||
* object, not the wrapper</li>
|
|
||||||
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
* <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for
|
||||||
* references to the {@link java.lang.reflect.Method method}, target object, and
|
* references to the {@link java.lang.reflect.Method method}, target object, and
|
||||||
* affected cache(s) respectively.</li>
|
* affected cache(s) respectively.</li>
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.lang.reflect.Proxy;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -417,7 +416,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collect puts from any @Cacheable miss, if no cached item is found
|
// Collect puts from any @Cacheable miss, if no cached item is found
|
||||||
List<CachePutRequest> cachePutRequests = new LinkedList<>();
|
List<CachePutRequest> cachePutRequests = new ArrayList<>();
|
||||||
if (cacheHit == null) {
|
if (cacheHit == null) {
|
||||||
collectPutRequests(contexts.get(CacheableOperation.class), cacheValue, cachePutRequests);
|
collectPutRequests(contexts.get(CacheableOperation.class), cacheValue, cachePutRequests);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
<cache:cache-put method="multiUpdate" cache="primary"/>
|
<cache:cache-put method="multiUpdate" cache="primary"/>
|
||||||
<cache:cache-put method="multiUpdate" cache="secondary"/>
|
<cache:cache-put method="multiUpdate" cache="secondary"/>
|
||||||
<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
|
<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
|
||||||
|
<cache:cache-put method="putEvaluatesUnlessBeforeKey" cache="primary" key="#result.id" unless="#result == null"/>
|
||||||
</cache:caching>
|
</cache:caching>
|
||||||
</cache:advice>
|
</cache:advice>
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@
|
|||||||
<cache:cache-put method="multiUpdate" cache="primary"/>
|
<cache:cache-put method="multiUpdate" cache="primary"/>
|
||||||
<cache:cache-put method="multiUpdate" cache="secondary"/>
|
<cache:cache-put method="multiUpdate" cache="secondary"/>
|
||||||
<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
|
<cache:cache-put method="putRefersToResult" cache="primary" key="#result.id"/>
|
||||||
|
<cache:cache-put method="putEvaluatesUnlessBeforeKey" cache="primary" key="#result.id" unless="#result == null"/>
|
||||||
</cache:caching>
|
</cache:caching>
|
||||||
</cache:advice>
|
</cache:advice>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -31,13 +31,10 @@ import org.springframework.context.ConfigurableApplicationContext;
|
|||||||
import org.springframework.context.testfixture.cache.beans.AnnotatedClassCacheableService;
|
import org.springframework.context.testfixture.cache.beans.AnnotatedClassCacheableService;
|
||||||
import org.springframework.context.testfixture.cache.beans.CacheableService;
|
import org.springframework.context.testfixture.cache.beans.CacheableService;
|
||||||
import org.springframework.context.testfixture.cache.beans.TestEntity;
|
import org.springframework.context.testfixture.cache.beans.TestEntity;
|
||||||
import org.springframework.expression.spel.SpelEvaluationException;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract cache annotation tests (containing several reusable methods).
|
* Abstract cache annotation tests (containing several reusable methods).
|
||||||
@@ -507,27 +504,24 @@ public abstract class AbstractCacheAnnotationTests {
|
|||||||
assertThat(primary.get(id).get()).isSameAs(entity);
|
assertThat(primary.get(id).get()).isSameAs(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPutRefersToNullResult(CacheableService<?> service) {
|
protected void testPutRefersToResultWithUnless(CacheableService<?> service) {
|
||||||
Long id = Long.MIN_VALUE;
|
Long id = 42L;
|
||||||
TestEntity entity = new TestEntity();
|
TestEntity entity = new TestEntity();
|
||||||
|
entity.setId(id);
|
||||||
Cache primary = this.cm.getCache("primary");
|
Cache primary = this.cm.getCache("primary");
|
||||||
assertNull(primary.get(id));
|
assertThat(primary.get(id)).isNull();
|
||||||
try {
|
assertThat(service.putEvaluatesUnlessBeforeKey(entity)).isNotNull();
|
||||||
service.putRefersToNullResult(entity);
|
assertThat(primary.get(id).get()).isSameAs(entity);
|
||||||
} catch (Exception e) {
|
|
||||||
assertEquals(SpelEvaluationException.class, e.getClass());
|
|
||||||
assertEquals("EL1007E: Property or field 'id' cannot be found on null", e.getMessage());
|
|
||||||
}
|
|
||||||
assertNull(primary.get(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPutRefersToNullResultWithUnless(CacheableService<?> service) {
|
protected void testPutEvaluatesUnlessBeforeKey(CacheableService<?> service) {
|
||||||
Long id = Long.MIN_VALUE;
|
Long id = Long.MIN_VALUE; // return null
|
||||||
TestEntity entity = new TestEntity();
|
TestEntity entity = new TestEntity();
|
||||||
|
entity.setId(id);
|
||||||
Cache primary = this.cm.getCache("primary");
|
Cache primary = this.cm.getCache("primary");
|
||||||
assertNull(primary.get(id));
|
assertThat(primary.get(id)).isNull();
|
||||||
service.putRefersToNullResultWithUnless(entity);
|
assertThat(service.putEvaluatesUnlessBeforeKey(entity)).isNull();
|
||||||
assertNull(primary.get(id));
|
assertThat(primary.get(id)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void testMultiCacheAndEvict(CacheableService<?> service) {
|
protected void testMultiCacheAndEvict(CacheableService<?> service) {
|
||||||
@@ -875,29 +869,29 @@ public abstract class AbstractCacheAnnotationTests {
|
|||||||
testPutRefersToResult(this.cs);
|
testPutRefersToResult(this.cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutRefersToResultWithUnless() {
|
||||||
|
testPutRefersToResultWithUnless(this.cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutEvaluatesUnlessBeforeKey() {
|
||||||
|
testPutEvaluatesUnlessBeforeKey(this.cs);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClassPutRefersToResult() {
|
public void testClassPutRefersToResult() {
|
||||||
testPutRefersToResult(this.ccs);
|
testPutRefersToResult(this.ccs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPutRefersToNullResult() throws Exception {
|
public void testClassPutRefersToResultWithUnless(){
|
||||||
testPutRefersToNullResult(this.cs);
|
testPutRefersToResultWithUnless(this.ccs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClassPutRefersToNullResult() throws Exception {
|
public void testClassPutEvaluatesUnlessBeforeKey(){
|
||||||
testPutRefersToNullResult(this.ccs);
|
testPutEvaluatesUnlessBeforeKey(this.ccs);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPutRefersToNullResultWithUnless() throws Exception {
|
|
||||||
testPutRefersToNullResultWithUnless(this.cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClassPutRefersToNullResultWithUnless() throws Exception {
|
|
||||||
testPutRefersToNullResultWithUnless(this.ccs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -236,14 +236,9 @@ public class AnnotatedClassCacheableService implements CacheableService<Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@CachePut(cacheNames = "primary", key = "#result.id")
|
@CachePut(cacheNames = "primary", key = "#result.id", unless = "#result == null")
|
||||||
public TestEntity putRefersToNullResult(TestEntity arg1) {
|
public TestEntity putEvaluatesUnlessBeforeKey(TestEntity arg1) {
|
||||||
return null;
|
return (arg1.getId() != Long.MIN_VALUE ? arg1 : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@CachePut(cacheNames = "primary", key = "#result.id", unless = "#result == null")
|
|
||||||
public TestEntity putRefersToNullResultWithUnless(TestEntity arg1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -93,8 +93,6 @@ public interface CacheableService<T> {
|
|||||||
|
|
||||||
TestEntity putRefersToResult(TestEntity arg1);
|
TestEntity putRefersToResult(TestEntity arg1);
|
||||||
|
|
||||||
TestEntity putRefersToNullResult(TestEntity arg1);
|
TestEntity putEvaluatesUnlessBeforeKey(TestEntity arg1);
|
||||||
|
|
||||||
TestEntity putRefersToNullResultWithUnless(TestEntity arg1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -244,14 +244,9 @@ public class DefaultCacheableService implements CacheableService<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@CachePut(cacheNames = "primary", key = "#result.id")
|
@CachePut(cacheNames = "primary", key = "#result.id", unless = "#result == null")
|
||||||
public TestEntity putRefersToNullResult(TestEntity arg1) {
|
public TestEntity putEvaluatesUnlessBeforeKey(TestEntity arg1) {
|
||||||
return null;
|
return (arg1.getId() != Long.MIN_VALUE ? arg1 : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@CachePut(cacheNames = "primary", key = "#result.id", unless = "#result == null")
|
|
||||||
public TestEntity putRefersToNullResultWithUnless(TestEntity arg1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user