Polish contribution

Closes gh-4903
pull/5289/head
Stephane Nicoll 9 years ago
parent 98cc68364a
commit 6741f05af1

@ -76,17 +76,6 @@ public class CacheStatisticsAutoConfiguration {
} }
@Configuration
@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
static class CaffeineCacheStatisticsProviderConfiguration {
@Bean
public CaffeineCacheStatisticsProvider caffeineCacheStatisticsProvider() {
return new CaffeineCacheStatisticsProvider();
}
}
@Configuration @Configuration
@ConditionalOnClass({ EhCacheCache.class, Ehcache.class, StatisticsGateway.class }) @ConditionalOnClass({ EhCacheCache.class, Ehcache.class, StatisticsGateway.class })
static class EhCacheCacheStatisticsProviderConfiguration { static class EhCacheCacheStatisticsProviderConfiguration {
@ -119,6 +108,17 @@ public class CacheStatisticsAutoConfiguration {
} }
@Configuration
@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
static class CaffeineCacheStatisticsProviderConfiguration {
@Bean
public CaffeineCacheStatisticsProvider caffeineCacheStatisticsProvider() {
return new CaffeineCacheStatisticsProvider();
}
}
@Configuration @Configuration
@ConditionalOnClass({ com.google.common.cache.Cache.class, GuavaCache.class }) @ConditionalOnClass({ com.google.common.cache.Cache.class, GuavaCache.class })
static class GuavaCacheStatisticsConfiguration { static class GuavaCacheStatisticsConfiguration {

@ -118,6 +118,14 @@ public class CacheStatisticsAutoConfigurationTests {
doTestCoreStatistics(provider, true); doTestCoreStatistics(provider, true);
} }
@Test
public void baseCaffeineCacheStatistics() {
load(CaffeineCacheConfig.class);
CacheStatisticsProvider provider = this.context
.getBean("caffeineCacheStatisticsProvider", CacheStatisticsProvider.class);
doTestCoreStatistics(provider, true);
}
@Test @Test
public void concurrentMapCacheStatistics() { public void concurrentMapCacheStatistics() {
load(ConcurrentMapConfig.class); load(ConcurrentMapConfig.class);
@ -148,14 +156,6 @@ public class CacheStatisticsAutoConfigurationTests {
assertCoreStatistics(updatedCacheStatistics, null, null, null); assertCoreStatistics(updatedCacheStatistics, null, null, null);
} }
@Test
public void caffeineCacheStatistics() {
load(CaffeineCacheConfig.class);
CacheStatisticsProvider provider = this.context
.getBean("caffeineCacheStatisticsProvider", CacheStatisticsProvider.class);
doTestCoreStatistics(provider, true);
}
private void doTestCoreStatistics(CacheStatisticsProvider provider, private void doTestCoreStatistics(CacheStatisticsProvider provider,
boolean supportSize) { boolean supportSize) {
Cache books = getCache("books"); Cache books = getCache("books");

@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.cache; package org.springframework.boot.autoconfigure.cache;
import java.util.List;
import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec; import com.github.benmanes.caffeine.cache.CaffeineSpec;
@ -23,10 +25,12 @@ import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -37,13 +41,16 @@ import org.springframework.util.StringUtils;
*/ */
@Configuration @Configuration
@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class }) @ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
@ConditionalOnMissingBean(org.springframework.cache.CacheManager.class) @ConditionalOnMissingBean(CacheManager.class)
@Conditional({ CacheCondition.class }) @Conditional({ CacheCondition.class })
class CaffeineCacheConfiguration { class CaffeineCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
private CacheManagerCustomizers customizers;
@Autowired(required = false) @Autowired(required = false)
private Caffeine<Object, Object> caffeine; private Caffeine<Object, Object> caffeine;
@ -54,27 +61,34 @@ class CaffeineCacheConfiguration {
private CacheLoader<Object, Object> cacheLoader; private CacheLoader<Object, Object> cacheLoader;
@Bean @Bean
@ConditionalOnMissingBean
public CaffeineCacheManager caffeineCacheManager() { public CaffeineCacheManager caffeineCacheManager() {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(); CaffeineCacheManager cacheManager = createCacheManager();
setCacheBuilder(caffeineCacheManager); List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!CollectionUtils.isEmpty(cacheNames)) {
cacheManager.setCacheNames(cacheNames);
}
return this.customizers.customize(cacheManager);
}
private CaffeineCacheManager createCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
setCacheBuilder(cacheManager);
if (this.cacheLoader != null) { if (this.cacheLoader != null) {
caffeineCacheManager.setCacheLoader(this.cacheLoader); cacheManager.setCacheLoader(this.cacheLoader);
} }
caffeineCacheManager.setCacheNames(this.cacheProperties.getCacheNames()); return cacheManager;
return caffeineCacheManager;
} }
private void setCacheBuilder(CaffeineCacheManager caffeineCacheManager) { private void setCacheBuilder(CaffeineCacheManager cacheManager) {
String specification = this.cacheProperties.getCaffeine().getSpec(); String specification = this.cacheProperties.getCaffeine().getSpec();
if (StringUtils.hasText(specification)) { if (StringUtils.hasText(specification)) {
caffeineCacheManager.setCaffeine(Caffeine.from(specification)); cacheManager.setCacheSpecification(specification);
} }
else if (this.caffeineSpec != null) { else if (this.caffeineSpec != null) {
caffeineCacheManager.setCaffeine(Caffeine.from(this.caffeineSpec)); cacheManager.setCaffeineSpec(this.caffeineSpec);
} }
else if (this.caffeine != null) { else if (this.caffeine != null) {
caffeineCacheManager.setCaffeine(this.caffeine); cacheManager.setCaffeine(this.caffeine);
} }
} }

@ -584,45 +584,52 @@ public class CacheAutoConfigurationTests {
validateGuavaCacheWithStats(); validateGuavaCacheWithStats();
} }
private void validateGuavaCacheWithStats() {
GuavaCacheManager cacheManager = validateCacheManager(GuavaCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
Cache foo = cacheManager.getCache("foo");
foo.get("1");
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount()).isEqualTo(1L);
}
@Test @Test
public void caffeineCacheWithCaches() { public void caffeineCacheWithExplicitCaches() {
load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine", load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine",
"spring.cache.cacheNames[0]=spring", "spring.cache.cacheNames[1]=boot"); "spring.cache.cacheNames=foo");
CaffeineCacheManager cacheManager = validateCacheManager( CaffeineCacheManager cacheManager = validateCacheManager(
CaffeineCacheManager.class); CaffeineCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("spring", "boot"); assertThat(cacheManager.getCacheNames()).containsOnly("foo");
Cache foo = cacheManager.getCache("foo");
foo.get("1");
// See next tests: no spec given so stats should be disabled
assertThat(((CaffeineCache) foo).getNativeCache().stats().missCount()).isEqualTo(0L);
} }
@Test @Test
public void caffeineCacheNotAllowNullValues() { public void caffeineCacheWithCustomizers() {
load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine", testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "caffeine",
"spring.cache.caffeine.allow-null-values=false"); "allCacheManagerCustomizer", "caffeineCacheManagerCustomizer");
CaffeineCacheManager cacheManager = validateCacheManager(
CaffeineCacheManager.class);
assertThat(cacheManager.isAllowNullValues()).isFalse();
} }
@Test @Test
public void caffeineCacheWithNullCaches() { public void caffeineCacheWithExplicitCacheBuilder() {
load(CaffeineCacheBuilderConfiguration.class, "spring.cache.type=caffeine", load(CaffeineCacheBuilderConfiguration.class, "spring.cache.type=caffeine",
"spring.cache.cacheNames[0]=caffeine", "spring.cache.cacheNames[1]=cache"); "spring.cache.cacheNames=foo,bar");
CaffeineCacheManager cacheManager = validateCacheManager( validateCaffeineCacheWithStats();
CaffeineCacheManager.class);
assertThat(cacheManager.isAllowNullValues()).isTrue();
} }
@Test @Test
public void caffeineCacheExplicitWithSpec() { public void caffeineCacheExplicitWithSpec() {
load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine", load(CaffeineCacheSpecConfiguration.class, "spring.cache.type=caffeine",
"spring.cache.caffeine.spec=recordStats", "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
"spring.cache.cacheNames[1]=bar");
validateCaffeineCacheWithStats(); validateCaffeineCacheWithStats();
} }
@Test @Test
public void caffeineCacheExplicitWithCacheBuilder() { public void caffeineCacheExplicitWithSpecString() {
load(CaffeineCacheBuilderConfiguration2.class, "spring.cache.type=caffeine", load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine",
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); "spring.cache.caffeine.spec=recordStats", "spring.cache.cacheNames[0]=foo",
"spring.cache.cacheNames[1]=bar");
validateCaffeineCacheWithStats(); validateCaffeineCacheWithStats();
} }
@ -634,14 +641,6 @@ public class CacheAutoConfigurationTests {
assertThat(((CaffeineCache) foo).getNativeCache().stats().missCount()).isEqualTo(1L); assertThat(((CaffeineCache) foo).getNativeCache().stats().missCount()).isEqualTo(1L);
} }
private void validateGuavaCacheWithStats() {
GuavaCacheManager cacheManager = validateCacheManager(GuavaCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
Cache foo = cacheManager.getCache("foo");
foo.get("1");
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount()).isEqualTo(1L);
}
private <T extends CacheManager> T validateCacheManager(Class<T> type) { private <T extends CacheManager> T validateCacheManager(Class<T> type) {
CacheManager cacheManager = this.context.getBean(CacheManager.class); CacheManager cacheManager = this.context.getBean(CacheManager.class);
assertThat(cacheManager).as("Wrong cache manager type").isInstanceOf(type); assertThat(cacheManager).as("Wrong cache manager type").isInstanceOf(type);
@ -897,14 +896,14 @@ public class CacheAutoConfigurationTests {
@Bean @Bean
Caffeine<Object, Object> cacheBuilder() { Caffeine<Object, Object> cacheBuilder() {
return Caffeine.newBuilder().maximumSize(10); return Caffeine.newBuilder().recordStats();
} }
} }
@Configuration @Configuration
@EnableCaching @EnableCaching
static class CaffeineCacheBuilderConfiguration2 { static class CaffeineCacheSpecConfiguration {
@Bean @Bean
CaffeineSpec caffeineSpec() { CaffeineSpec caffeineSpec() {
@ -964,6 +963,12 @@ public class CacheAutoConfigurationTests {
}; };
} }
@Bean
public CacheManagerCustomizer<CaffeineCacheManager> caffeineCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<CaffeineCacheManager>() {
};
}
} }
static abstract class CacheManagerTestCustomizer<T extends CacheManager> static abstract class CacheManagerTestCustomizer<T extends CacheManager>

@ -3249,6 +3249,7 @@ Spring Boot tries to detect the following providers (in this order):
* <<boot-features-caching-provider-hazelcast,Hazelcast>> * <<boot-features-caching-provider-hazelcast,Hazelcast>>
* <<boot-features-caching-provider-infinispan,Infinispan>> * <<boot-features-caching-provider-infinispan,Infinispan>>
* <<boot-features-caching-provider-redis,Redis>> * <<boot-features-caching-provider-redis,Redis>>
* <<boot-features-caching-provider-caffeine,Caffeine>>
* <<boot-features-caching-provider-guava,Guava>> * <<boot-features-caching-provider-guava,Guava>>
* <<boot-features-caching-provider-simple,Simple>> * <<boot-features-caching-provider-simple,Simple>>
@ -3384,6 +3385,31 @@ recommend to keep this setting enabled if you create your own `RedisCacheManager
[[boot-features-caching-provider-caffeine]]
==== Caffeine
Caffeine is a Java 8 rewrite of Guavas cache and will supersede the Guava support in
Spring Boot 2.0. If Caffeine is present, a `CaffeineCacheManager` is auto-configured.
Caches can be created on startup using the `spring.cache.cache-names` property and
customized by one of the following (in this order):
1. A cache spec defined by `spring.cache.caffeine.spec`
2. A `com.github.benmanes.caffeine.cache.CaffeineSpec` bean is defined
3. A `com.github.benmanes.caffeine.cache.Caffeine` bean is defined
For instance, the following configuration creates a `foo` and `bar` caches with a maximum
size of 500 and a _time to live_ of 10 minutes
[source,properties,indent=0]
----
spring.cache.cache-names=foo,bar
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
----
Besides, if a `com.github.benmanes.caffeine.cache.CacheLoader` bean is defined, it is
automatically associated to the `CaffeineCacheManager`.
[[boot-features-caching-provider-guava]] [[boot-features-caching-provider-guava]]
==== Guava ==== Guava
If Guava is present, a `GuavaCacheManager` is auto-configured. Caches can be created If Guava is present, a `GuavaCacheManager` is auto-configured. Caches can be created

@ -84,6 +84,13 @@ a redis instance with the default settings is expected on your local box).
=== Caffeine
Simply add the `com.github.ben-manes.caffeine:caffeine` dependency to enable support
for Caffeine. You can customize how caches are created in different ways, see
`application.properties` for an example and the documentation for more details.
=== Guava === Guava
Spring Boot does not provide any dependency management for _Guava_ so you'll have to add Spring Boot does not provide any dependency management for _Guava_ so you'll have to add
the `com.google.guava:guava` dependency with a version. You can customize how caches are the `com.google.guava:guava` dependency with a version. You can customize how caches are

@ -10,6 +10,12 @@
#spring.cache.jcache.config=hazelcast.xml #spring.cache.jcache.config=hazelcast.xml
#
# Caffeine configuration
#
#spring.cache.caffeine.spec=maximumSize=200,expireAfterAccess=600s
# #
# Guava configuration # Guava configuration
# #

Loading…
Cancel
Save