Commit 0e43f420 authored by Stephane Nicoll's avatar Stephane Nicoll

Merge branch '1.3.x'

parents ef44d660 5febd497
...@@ -66,7 +66,7 @@ import org.springframework.util.Assert; ...@@ -66,7 +66,7 @@ import org.springframework.util.Assert;
@EnableConfigurationProperties(CacheProperties.class) @EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class) @AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
@AutoConfigureAfter({ HazelcastAutoConfiguration.class, RedisAutoConfiguration.class }) @AutoConfigureAfter({ HazelcastAutoConfiguration.class, RedisAutoConfiguration.class })
@Import(CacheConfigurationImportSelector.class) @Import({ CacheManagerCustomizerInvoker.class, CacheConfigurationImportSelector.class })
public class CacheAutoConfiguration { public class CacheAutoConfiguration {
static final String VALIDATOR_BEAN_NAME = "cacheAutoConfigurationValidator"; static final String VALIDATOR_BEAN_NAME = "cacheAutoConfigurationValidator";
......
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.cache;
import org.springframework.cache.CacheManager;
/**
* Callback interface that can be implemented by beans wishing to customize the cache
* manager before it is fully initialized, in particular to tune its configuration.
*
* @author Stephane Nicoll
* @since 1.3.3
*/
public interface CacheManagerCustomizer<C extends CacheManager> {
/**
* Customize the cache manager.
* @param cacheManager the {@code CacheManager} to customize
*/
void customize(C cacheManager);
}
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.cache;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
/**
* Invoke the available {@link CacheManagerCustomizer} instances in the context for a
* given {@link CacheManager}.
*
* @author Stephane Nicoll
*/
class CacheManagerCustomizerInvoker implements ApplicationContextAware {
private ConfigurableApplicationContext applicationContext;
/**
* Customize the specified {@link CacheManager}. Locates all {@link CacheManagerCustomizer}
* beans able to handle the specified instance and invoke
* {@link CacheManagerCustomizer#customize(CacheManager)} on them.
* @param cacheManager the cache manager to customize
*/
public void customize(CacheManager cacheManager) {
List<CacheManagerCustomizer<CacheManager>> customizers = findCustomizers(cacheManager);
AnnotationAwareOrderComparator.sort(customizers);
for (CacheManagerCustomizer<CacheManager> customizer : customizers) {
customizer.customize(cacheManager);
}
}
@SuppressWarnings("unchecked")
private List<CacheManagerCustomizer<CacheManager>> findCustomizers(CacheManager cacheManager) {
if (this.applicationContext == null) {
return Collections.emptyList();
}
Map<String, CacheManagerCustomizer> map = BeanFactoryUtils
.beansOfTypeIncludingAncestors(this.applicationContext.getBeanFactory(), CacheManagerCustomizer.class);
List<CacheManagerCustomizer<CacheManager>> customizers
= new ArrayList<CacheManagerCustomizer<CacheManager>>();
for (CacheManagerCustomizer customizer : map.values()) {
Class<?> target = GenericTypeResolver.resolveTypeArgument(
customizer.getClass(), CacheManagerCustomizer.class);
if (target == null || target.isAssignableFrom(cacheManager.getClass())) {
customizers.add(customizer);
}
}
return customizers;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof ConfigurableApplicationContext) {
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
}
}
...@@ -48,9 +48,14 @@ class EhCacheCacheConfiguration { ...@@ -48,9 +48,14 @@ class EhCacheCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) { public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
return new EhCacheCacheManager(ehCacheCacheManager); EhCacheCacheManager cacheManager = new EhCacheCacheManager(ehCacheCacheManager);
this.customizerInvoker.customize(cacheManager);
return cacheManager;
} }
@Bean @Bean
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.cache; ...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.cache;
import java.util.Collection; import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
...@@ -40,10 +41,14 @@ import org.springframework.context.annotation.Configuration; ...@@ -40,10 +41,14 @@ import org.springframework.context.annotation.Configuration;
@Conditional(CacheCondition.class) @Conditional(CacheCondition.class)
class GenericCacheConfiguration { class GenericCacheConfiguration {
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public SimpleCacheManager cacheManager(Collection<Cache> caches) { public SimpleCacheManager cacheManager(Collection<Cache> caches) {
SimpleCacheManager cacheManager = new SimpleCacheManager(); SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(caches); cacheManager.setCaches(caches);
this.customizerInvoker.customize(cacheManager);
return cacheManager; return cacheManager;
} }
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -48,6 +48,9 @@ class GuavaCacheConfiguration { ...@@ -48,6 +48,9 @@ class GuavaCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Autowired(required = false) @Autowired(required = false)
private CacheBuilder<Object, Object> cacheBuilder; private CacheBuilder<Object, Object> cacheBuilder;
...@@ -64,6 +67,7 @@ class GuavaCacheConfiguration { ...@@ -64,6 +67,7 @@ class GuavaCacheConfiguration {
if (!CollectionUtils.isEmpty(cacheNames)) { if (!CollectionUtils.isEmpty(cacheNames)) {
cacheManager.setCacheNames(cacheNames); cacheManager.setCacheNames(cacheNames);
} }
this.customizerInvoker.customize(cacheManager);
return cacheManager; return cacheManager;
} }
......
...@@ -48,6 +48,9 @@ abstract class HazelcastInstanceConfiguration { ...@@ -48,6 +48,9 @@ abstract class HazelcastInstanceConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public HazelcastCacheManager cacheManager( public HazelcastCacheManager cacheManager(
HazelcastInstance existingHazelcastInstance) throws IOException { HazelcastInstance existingHazelcastInstance) throws IOException {
...@@ -58,7 +61,9 @@ abstract class HazelcastInstanceConfiguration { ...@@ -58,7 +61,9 @@ abstract class HazelcastInstanceConfiguration {
location).getHazelcastInstance(); location).getHazelcastInstance();
return new CloseableHazelcastCacheManager(cacheHazelcastInstance); return new CloseableHazelcastCacheManager(cacheHazelcastInstance);
} }
return new HazelcastCacheManager(existingHazelcastInstance); HazelcastCacheManager cacheManager = new HazelcastCacheManager(existingHazelcastInstance);
this.customizerInvoker.customize(cacheManager);
return cacheManager;
} }
} }
...@@ -70,6 +75,9 @@ abstract class HazelcastInstanceConfiguration { ...@@ -70,6 +75,9 @@ abstract class HazelcastInstanceConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public HazelcastInstance hazelcastInstance() throws IOException { public HazelcastInstance hazelcastInstance() throws IOException {
Resource config = this.cacheProperties.getHazelcast().getConfig(); Resource config = this.cacheProperties.getHazelcast().getConfig();
...@@ -82,7 +90,9 @@ abstract class HazelcastInstanceConfiguration { ...@@ -82,7 +90,9 @@ abstract class HazelcastInstanceConfiguration {
@Bean @Bean
public HazelcastCacheManager cacheManager() throws IOException { public HazelcastCacheManager cacheManager() throws IOException {
return new HazelcastCacheManager(hazelcastInstance()); HazelcastCacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance());
this.customizerInvoker.customize(cacheManager);
return cacheManager;
} }
} }
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -51,13 +51,18 @@ public class InfinispanCacheConfiguration { ...@@ -51,13 +51,18 @@ public class InfinispanCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Autowired(required = false) @Autowired(required = false)
private ConfigurationBuilder defaultConfigurationBuilder; private ConfigurationBuilder defaultConfigurationBuilder;
@Bean @Bean
public SpringEmbeddedCacheManager cacheManager( public SpringEmbeddedCacheManager cacheManager(
EmbeddedCacheManager embeddedCacheManager) { EmbeddedCacheManager embeddedCacheManager) {
return new SpringEmbeddedCacheManager(embeddedCacheManager); SpringEmbeddedCacheManager cacheManager = new SpringEmbeddedCacheManager(embeddedCacheManager);
this.customizerInvoker.customize(cacheManager);
return cacheManager;
} }
@Bean(destroyMethod = "stop") @Bean(destroyMethod = "stop")
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -63,6 +63,9 @@ class JCacheCacheConfiguration { ...@@ -63,6 +63,9 @@ class JCacheCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Autowired(required = false) @Autowired(required = false)
private javax.cache.configuration.Configuration<?, ?> defaultCacheConfiguration; private javax.cache.configuration.Configuration<?, ?> defaultCacheConfiguration;
...@@ -71,7 +74,9 @@ class JCacheCacheConfiguration { ...@@ -71,7 +74,9 @@ class JCacheCacheConfiguration {
@Bean @Bean
public JCacheCacheManager cacheManager(CacheManager jCacheCacheManager) { public JCacheCacheManager cacheManager(CacheManager jCacheCacheManager) {
return new JCacheCacheManager(jCacheCacheManager); JCacheCacheManager cacheManager = new JCacheCacheManager(jCacheCacheManager);
this.customizerInvoker.customize(cacheManager);
return cacheManager;
} }
@Bean @Bean
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -46,6 +46,9 @@ class RedisCacheConfiguration { ...@@ -46,6 +46,9 @@ class RedisCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) { public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
...@@ -53,6 +56,7 @@ class RedisCacheConfiguration { ...@@ -53,6 +56,7 @@ class RedisCacheConfiguration {
if (!cacheNames.isEmpty()) { if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames); cacheManager.setCacheNames(cacheNames);
} }
this.customizerInvoker.customize(cacheManager);
return cacheManager; return cacheManager;
} }
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 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.
...@@ -40,6 +40,9 @@ class SimpleCacheConfiguration { ...@@ -40,6 +40,9 @@ class SimpleCacheConfiguration {
@Autowired @Autowired
private CacheProperties cacheProperties; private CacheProperties cacheProperties;
@Autowired
CacheManagerCustomizerInvoker customizerInvoker;
@Bean @Bean
public ConcurrentMapCacheManager cacheManager() { public ConcurrentMapCacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(); ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
...@@ -47,6 +50,7 @@ class SimpleCacheConfiguration { ...@@ -47,6 +50,7 @@ class SimpleCacheConfiguration {
if (!cacheNames.isEmpty()) { if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames); cacheManager.setCacheNames(cacheNames);
} }
this.customizerInvoker.customize(cacheManager);
return cacheManager; return cacheManager;
} }
......
...@@ -17,8 +17,12 @@ ...@@ -17,8 +17,12 @@
package org.springframework.boot.autoconfigure.cache; package org.springframework.boot.autoconfigure.cache;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.cache.configuration.CompleteConfiguration; import javax.cache.configuration.CompleteConfiguration;
import javax.cache.configuration.MutableConfiguration; import javax.cache.configuration.MutableConfiguration;
...@@ -140,6 +144,12 @@ public class CacheAutoConfigurationTests { ...@@ -140,6 +144,12 @@ public class CacheAutoConfigurationTests {
assertThat(cacheManager.getCacheNames()).isEmpty(); assertThat(cacheManager.getCacheNames()).isEmpty();
} }
@Test
public void simpleCacheWithCustomizers() {
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "simple",
"allCacheManagerCustomizer", "simpleCacheManagerCustomizer");
}
@Test @Test
public void simpleCacheExplicitWithCacheNames() { public void simpleCacheExplicitWithCacheNames() {
load(DefaultCacheConfiguration.class, "spring.cache.type=simple", load(DefaultCacheConfiguration.class, "spring.cache.type=simple",
...@@ -168,6 +178,12 @@ public class CacheAutoConfigurationTests { ...@@ -168,6 +178,12 @@ public class CacheAutoConfigurationTests {
load(DefaultCacheConfiguration.class, "spring.cache.type=generic"); load(DefaultCacheConfiguration.class, "spring.cache.type=generic");
} }
@Test
public void genericCacheWithCustomizers() {
testCustomizers(GenericCacheAndCustomizersConfiguration.class, "generic",
"allCacheManagerCustomizer", "genericCacheManagerCustomizer");
}
@Test @Test
public void genericCacheExplicitWithCaches() { public void genericCacheExplicitWithCaches() {
load(GenericCacheConfiguration.class, "spring.cache.type=generic"); load(GenericCacheConfiguration.class, "spring.cache.type=generic");
...@@ -186,6 +202,12 @@ public class CacheAutoConfigurationTests { ...@@ -186,6 +202,12 @@ public class CacheAutoConfigurationTests {
assertThat(cacheManager.getCacheNames()).isEmpty(); assertThat(cacheManager.getCacheNames()).isEmpty();
} }
@Test
public void redisCacheWithCustomizers() {
testCustomizers(RedisCacheAndCustomizersConfiguration.class, "redis",
"allCacheManagerCustomizer", "redisCacheManagerCustomizer");
}
@Test @Test
public void redisCacheExplicitWithCaches() { public void redisCacheExplicitWithCaches() {
load(RedisCacheConfiguration.class, "spring.cache.type=redis", load(RedisCacheConfiguration.class, "spring.cache.type=redis",
...@@ -298,6 +320,12 @@ public class CacheAutoConfigurationTests { ...@@ -298,6 +320,12 @@ public class CacheAutoConfigurationTests {
.isEqualTo(cacheManager.getCacheManager()); .isEqualTo(cacheManager.getCacheManager());
} }
@Test
public void ehCacheCacheWithCustomizers() {
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "ehcache",
"allCacheManagerCustomizer", "ehCacheCacheManagerCustomizer");
}
@Test @Test
public void ehCacheCacheWithConfig() { public void ehCacheCacheWithConfig() {
load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache", load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache",
...@@ -329,6 +357,12 @@ public class CacheAutoConfigurationTests { ...@@ -329,6 +357,12 @@ public class CacheAutoConfigurationTests {
.isEqualTo(getHazelcastInstance(cacheManager)); .isEqualTo(getHazelcastInstance(cacheManager));
} }
@Test
public void hazelcastCacheWithCustomizers() {
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "hazelcast",
"allCacheManagerCustomizer", "hazelcastCacheManagerCustomizer");
}
@Test @Test
public void hazelcastCacheWithConfig() throws IOException { public void hazelcastCacheWithConfig() throws IOException {
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast", load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
...@@ -441,6 +475,12 @@ public class CacheAutoConfigurationTests { ...@@ -441,6 +475,12 @@ public class CacheAutoConfigurationTests {
assertThat(cacheManager.getCacheNames()).contains("foo", "bar"); assertThat(cacheManager.getCacheNames()).contains("foo", "bar");
} }
@Test
public void infinispanCacheWithCustomizers() {
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "infinispan",
"allCacheManagerCustomizer", "infinispanCacheManagerCustomizer");
}
@Test @Test
public void infinispanCacheWithCaches() { public void infinispanCacheWithCaches() {
load(DefaultCacheConfiguration.class, "spring.cache.type=infinispan", load(DefaultCacheConfiguration.class, "spring.cache.type=infinispan",
...@@ -508,6 +548,12 @@ public class CacheAutoConfigurationTests { ...@@ -508,6 +548,12 @@ public class CacheAutoConfigurationTests {
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount()).isEqualTo(0L); assertThat(((GuavaCache) foo).getNativeCache().stats().missCount()).isEqualTo(0L);
} }
@Test
public void guavaCacheWithCustomizers() {
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "guava",
"allCacheManagerCustomizer", "guavaCacheManagerCustomizer");
}
@Test @Test
public void guavaCacheExplicitWithSpec() { public void guavaCacheExplicitWithSpec() {
load(DefaultCacheConfiguration.class, "spring.cache.type=guava", load(DefaultCacheConfiguration.class, "spring.cache.type=guava",
...@@ -537,6 +583,25 @@ public class CacheAutoConfigurationTests { ...@@ -537,6 +583,25 @@ public class CacheAutoConfigurationTests {
return type.cast(cacheManager); return type.cast(cacheManager);
} }
private void testCustomizers(Class<?> config, String cacheType, String... expectedCustomizerNames) {
load(config, "spring.cache.type=" + cacheType);
CacheManager cacheManager = validateCacheManager(CacheManager.class);
List<String> expected = new ArrayList<String>();
expected.addAll(Arrays.asList(expectedCustomizerNames));
Map<String, CacheManagerTestCustomizer> map =
this.context.getBeansOfType(CacheManagerTestCustomizer.class);
for (Map.Entry<String, CacheManagerTestCustomizer> entry : map.entrySet()) {
if (expected.contains(entry.getKey())) {
expected.remove(entry.getKey());
assertThat(entry.getValue().cacheManager).isSameAs(cacheManager);
}
else {
assertThat(entry.getValue().cacheManager).isNull();
}
}
assertThat(expected).hasSize(0);
}
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment); EnvironmentTestUtils.addEnvironment(applicationContext, environment);
...@@ -562,6 +627,13 @@ public class CacheAutoConfigurationTests { ...@@ -562,6 +627,13 @@ public class CacheAutoConfigurationTests {
} }
@Configuration
@EnableCaching
@Import(CacheManagerCustomizersConfiguration.class)
static class DefaultCacheAndCustomizersConfiguration {
}
@Configuration @Configuration
@EnableCaching @EnableCaching
static class GenericCacheConfiguration { static class GenericCacheConfiguration {
...@@ -578,6 +650,11 @@ public class CacheAutoConfigurationTests { ...@@ -578,6 +650,11 @@ public class CacheAutoConfigurationTests {
} }
@Configuration
@Import({GenericCacheConfiguration.class, CacheManagerCustomizersConfiguration.class})
static class GenericCacheAndCustomizersConfiguration {
}
@Configuration @Configuration
@EnableCaching @EnableCaching
static class RedisCacheConfiguration { static class RedisCacheConfiguration {
...@@ -589,6 +666,12 @@ public class CacheAutoConfigurationTests { ...@@ -589,6 +666,12 @@ public class CacheAutoConfigurationTests {
} }
@Configuration
@Import({RedisCacheConfiguration.class, CacheManagerCustomizersConfiguration.class})
static class RedisCacheAndCustomizersConfiguration {
}
@Configuration @Configuration
@EnableCaching @EnableCaching
static class JCacheCustomConfiguration { static class JCacheCustomConfiguration {
...@@ -662,8 +745,8 @@ public class CacheAutoConfigurationTests { ...@@ -662,8 +745,8 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@ImportAutoConfiguration({ CacheAutoConfiguration.class, @ImportAutoConfiguration({CacheAutoConfiguration.class,
HazelcastAutoConfiguration.class }) HazelcastAutoConfiguration.class})
static class HazelcastAndCacheConfiguration { static class HazelcastAndCacheConfiguration {
} }
...@@ -682,7 +765,7 @@ public class CacheAutoConfigurationTests { ...@@ -682,7 +765,7 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class }) @Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
static class CustomCacheManagerConfiguration { static class CustomCacheManagerConfiguration {
@Bean @Bean
...@@ -693,7 +776,7 @@ public class CacheAutoConfigurationTests { ...@@ -693,7 +776,7 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class }) @Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
static class CustomCacheManagerFromSupportConfiguration static class CustomCacheManagerFromSupportConfiguration
extends CachingConfigurerSupport { extends CachingConfigurerSupport {
...@@ -718,7 +801,7 @@ public class CacheAutoConfigurationTests { ...@@ -718,7 +801,7 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class }) @Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
static class CustomCacheResolverConfiguration extends CachingConfigurerSupport { static class CustomCacheResolverConfiguration extends CachingConfigurerSupport {
@Override @Override
...@@ -739,4 +822,64 @@ public class CacheAutoConfigurationTests { ...@@ -739,4 +822,64 @@ public class CacheAutoConfigurationTests {
} }
@Configuration
static class CacheManagerCustomizersConfiguration {
@Bean
public CacheManagerCustomizer<CacheManager> allCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<CacheManager>() {
};
}
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> simpleCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<ConcurrentMapCacheManager>() {
};
}
@Bean
public CacheManagerCustomizer<SimpleCacheManager> genericCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<SimpleCacheManager>() { };
}
@Bean
public CacheManagerCustomizer<RedisCacheManager> redisCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<RedisCacheManager>() { };
}
@Bean
public CacheManagerCustomizer<EhCacheCacheManager> ehCacheCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<EhCacheCacheManager>() { };
}
@Bean
public CacheManagerCustomizer<HazelcastCacheManager> hazelcastCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<HazelcastCacheManager>() { };
}
@Bean
public CacheManagerCustomizer<SpringEmbeddedCacheManager> infinispanCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<SpringEmbeddedCacheManager>() { };
}
@Bean
public CacheManagerCustomizer<GuavaCacheManager> guavaCacheManagerCustomizer() {
return new CacheManagerTestCustomizer<GuavaCacheManager>() { };
}
}
static abstract class CacheManagerTestCustomizer<C extends CacheManager> implements CacheManagerCustomizer<C> {
private C cacheManager;
@Override
public void customize(C cacheManager) {
if (this.cacheManager != null) {
throw new IllegalStateException("Customized invoked twice");
}
this.cacheManager = cacheManager;
}
}
} }
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.cache;
import java.util.Arrays;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
*
* @author Stephane Nicoll
*/
public class CacheManagerCustomizerInvokerTests {
private AnnotationConfigApplicationContext context;
@After
public void tearDown() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void customizeSimpleCacheManager() {
load(SimpleConfiguration.class, "spring.cache.type=simple");
ConcurrentMapCacheManager cacheManager = this.context.getBean(ConcurrentMapCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("one", "two");
}
@Test
public void customizeNoConfigurableApplicationContext() {
CacheManagerCustomizerInvoker invoker = new CacheManagerCustomizerInvoker();
ApplicationContext context = mock(ApplicationContext.class);
invoker.setApplicationContext(context);
invoker.customize(mock(CacheManager.class));
verifyZeroInteractions(context);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
applicationContext.register(config);
applicationContext.register(CacheAutoConfiguration.class);
applicationContext.refresh();
this.context = applicationContext;
}
@Configuration
@EnableCaching
static class SimpleConfiguration {
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
@Override
public void customize(ConcurrentMapCacheManager cacheManager) {
cacheManager.setCacheNames(Arrays.asList("one", "two"));
}
};
}
}
}
...@@ -3255,6 +3255,29 @@ Spring Boot tries to detect the following providers (in this order): ...@@ -3255,6 +3255,29 @@ Spring Boot tries to detect the following providers (in this order):
It is also possible to _force_ the cache provider to use via the `spring.cache.type` It is also possible to _force_ the cache provider to use via the `spring.cache.type`
property. property.
If the `CacheManager` is auto-configured by Spring Boot, you can further tune its
configuration before it is fully initialized by exposing a bean implementing the
`CacheManagerCustomizer` interface. The following set the cache names to use.
[source,java,indent=0]
----
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
@Override
public void customize(ConcurrentMapCacheManager cacheManager) {
cacheManager.setCacheNames(Arrays.asList("one", "two"));
}
};
}
----
[NOTE]
===
In the example above, a `ConcurrentMapCacheManager` is expected to be configured. If that
is not the case, the customizer won't be invoked at all. You can have as many customizers
as you want and you can also order them as usual using `@Order` or `Ordered`.
===
[[boot-features-caching-provider-generic]] [[boot-features-caching-provider-generic]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment