mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Support customization of CacheManager
This commit allows to customize the auto-configured `CacheManager` by exposing a bean of type `CacheManagerCustomizer`. The implementation may reference the type of a `CacheManager` to determine in which case it has to be invoked. Several implementations can be provided and ordered using the regular `Ordered` interface and `@Order` annotation. Closes gh-5039
This commit is contained in:
parent
ce71bd997c
commit
5febd497da
@ -66,7 +66,7 @@ import org.springframework.util.Assert;
|
||||
@EnableConfigurationProperties(CacheProperties.class)
|
||||
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
|
||||
@AutoConfigureAfter({ HazelcastAutoConfiguration.class, RedisAutoConfiguration.class })
|
||||
@Import(CacheConfigurationImportSelector.class)
|
||||
@Import({ CacheManagerCustomizerInvoker.class, CacheConfigurationImportSelector.class })
|
||||
public class CacheAutoConfiguration {
|
||||
|
||||
static final String VALIDATOR_BEAN_NAME = "cacheAutoConfigurationValidator";
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
|
||||
return new EhCacheCacheManager(ehCacheCacheManager);
|
||||
EhCacheCacheManager cacheManager = new EhCacheCacheManager(ehCacheCacheManager);
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
@ -40,10 +41,14 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Conditional(CacheCondition.class)
|
||||
class GenericCacheConfiguration {
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public SimpleCacheManager cacheManager(Collection<Cache> caches) {
|
||||
SimpleCacheManager cacheManager = new SimpleCacheManager();
|
||||
cacheManager.setCaches(caches);
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -48,6 +48,9 @@ class GuavaCacheConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheBuilder<Object, Object> cacheBuilder;
|
||||
|
||||
@ -64,6 +67,7 @@ class GuavaCacheConfiguration {
|
||||
if (!CollectionUtils.isEmpty(cacheNames)) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,9 @@ abstract class HazelcastInstanceConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public HazelcastCacheManager cacheManager(
|
||||
HazelcastInstance existingHazelcastInstance) throws IOException {
|
||||
@ -58,7 +61,9 @@ abstract class HazelcastInstanceConfiguration {
|
||||
location).getHazelcastInstance();
|
||||
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 {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public HazelcastInstance hazelcastInstance() throws IOException {
|
||||
Resource config = this.cacheProperties.getHazelcast().getConfig();
|
||||
@ -82,7 +90,9 @@ abstract class HazelcastInstanceConfiguration {
|
||||
|
||||
@Bean
|
||||
public HazelcastCacheManager cacheManager() throws IOException {
|
||||
return new HazelcastCacheManager(hazelcastInstance());
|
||||
HazelcastCacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance());
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -51,13 +51,18 @@ public class InfinispanCacheConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ConfigurationBuilder defaultConfigurationBuilder;
|
||||
|
||||
@Bean
|
||||
public SpringEmbeddedCacheManager cacheManager(
|
||||
EmbeddedCacheManager embeddedCacheManager) {
|
||||
return new SpringEmbeddedCacheManager(embeddedCacheManager);
|
||||
SpringEmbeddedCacheManager cacheManager = new SpringEmbeddedCacheManager(embeddedCacheManager);
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "stop")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -63,6 +63,9 @@ class JCacheCacheConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Autowired(required = false)
|
||||
private javax.cache.configuration.Configuration<?, ?> defaultCacheConfiguration;
|
||||
|
||||
@ -71,7 +74,9 @@ class JCacheCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
public JCacheCacheManager cacheManager(CacheManager jCacheCacheManager) {
|
||||
return new JCacheCacheManager(jCacheCacheManager);
|
||||
JCacheCacheManager cacheManager = new JCacheCacheManager(jCacheCacheManager);
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -46,6 +46,9 @@ class RedisCacheConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
|
||||
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
|
||||
@ -53,6 +56,7 @@ class RedisCacheConfiguration {
|
||||
if (!cacheNames.isEmpty()) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -40,6 +40,9 @@ class SimpleCacheConfiguration {
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCustomizerInvoker customizerInvoker;
|
||||
|
||||
@Bean
|
||||
public ConcurrentMapCacheManager cacheManager() {
|
||||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
|
||||
@ -47,6 +50,7 @@ class SimpleCacheConfiguration {
|
||||
if (!cacheNames.isEmpty()) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
this.customizerInvoker.customize(cacheManager);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,12 @@
|
||||
package org.springframework.boot.autoconfigure.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.cache.configuration.CompleteConfiguration;
|
||||
import javax.cache.configuration.MutableConfiguration;
|
||||
@ -70,6 +74,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
@ -150,6 +155,12 @@ public class CacheAutoConfigurationTests {
|
||||
assertThat(cacheManager.getCacheNames(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleCacheWithCustomizers() {
|
||||
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "simple",
|
||||
"allCacheManagerCustomizer", "simpleCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleCacheExplicitWithCacheNames() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=simple",
|
||||
@ -179,6 +190,12 @@ public class CacheAutoConfigurationTests {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=generic");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericCacheWithCustomizers() {
|
||||
testCustomizers(GenericCacheAndCustomizersConfiguration.class, "generic",
|
||||
"allCacheManagerCustomizer", "genericCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericCacheExplicitWithCaches() {
|
||||
load(GenericCacheConfiguration.class, "spring.cache.type=generic");
|
||||
@ -197,6 +214,12 @@ public class CacheAutoConfigurationTests {
|
||||
assertThat(cacheManager.getCacheNames(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisCacheWithCustomizers() {
|
||||
testCustomizers(RedisCacheAndCustomizersConfiguration.class, "redis",
|
||||
"allCacheManagerCustomizer", "redisCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisCacheExplicitWithCaches() {
|
||||
load(RedisCacheConfiguration.class, "spring.cache.type=redis",
|
||||
@ -315,6 +338,12 @@ public class CacheAutoConfigurationTests {
|
||||
equalTo(cacheManager.getCacheManager()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ehCacheCacheWithCustomizers() {
|
||||
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "ehcache",
|
||||
"allCacheManagerCustomizer", "ehCacheCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ehCacheCacheWithConfig() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache",
|
||||
@ -348,6 +377,12 @@ public class CacheAutoConfigurationTests {
|
||||
equalTo(getHazelcastInstance(cacheManager)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastCacheWithCustomizers() {
|
||||
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "hazelcast",
|
||||
"allCacheManagerCustomizer", "hazelcastCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastCacheWithConfig() throws IOException {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
|
||||
@ -461,6 +496,12 @@ public class CacheAutoConfigurationTests {
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void infinispanCacheWithCustomizers() {
|
||||
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "infinispan",
|
||||
"allCacheManagerCustomizer", "infinispanCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void infinispanCacheWithCaches() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=infinispan",
|
||||
@ -533,6 +574,12 @@ public class CacheAutoConfigurationTests {
|
||||
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount(), equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guavaCacheWithCustomizers() {
|
||||
testCustomizers(DefaultCacheAndCustomizersConfiguration.class, "guava",
|
||||
"allCacheManagerCustomizer", "guavaCacheManagerCustomizer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guavaCacheExplicitWithSpec() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=guava",
|
||||
@ -563,6 +610,28 @@ public class CacheAutoConfigurationTests {
|
||||
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("Customizer with name " + entry.getKey() + " should have been " +
|
||||
"invoked", entry.getValue().cacheManager, sameInstance(cacheManager));
|
||||
}
|
||||
else {
|
||||
assertThat("Customizer with name " + entry.getKey() + " should not have been" +
|
||||
"invoked", entry.getValue().cacheManager, nullValue());
|
||||
}
|
||||
}
|
||||
assertThat("The following customizers should have been invoked: " + expected,
|
||||
expected, hasSize(0));
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
@ -588,6 +657,13 @@ public class CacheAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@Import(CacheManagerCustomizersConfiguration.class)
|
||||
static class DefaultCacheAndCustomizersConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class GenericCacheConfiguration {
|
||||
@ -604,6 +680,11 @@ public class CacheAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({GenericCacheConfiguration.class, CacheManagerCustomizersConfiguration.class})
|
||||
static class GenericCacheAndCustomizersConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class RedisCacheConfiguration {
|
||||
@ -615,6 +696,12 @@ public class CacheAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({RedisCacheConfiguration.class, CacheManagerCustomizersConfiguration.class})
|
||||
static class RedisCacheAndCustomizersConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class JCacheCustomConfiguration {
|
||||
@ -688,8 +775,8 @@ public class CacheAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ CacheAutoConfiguration.class,
|
||||
HazelcastAutoConfiguration.class })
|
||||
@ImportAutoConfiguration({CacheAutoConfiguration.class,
|
||||
HazelcastAutoConfiguration.class})
|
||||
static class HazelcastAndCacheConfiguration {
|
||||
|
||||
}
|
||||
@ -708,7 +795,7 @@ public class CacheAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
@Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
|
||||
static class CustomCacheManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ -719,7 +806,7 @@ public class CacheAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
@Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
|
||||
static class CustomCacheManagerFromSupportConfiguration
|
||||
extends CachingConfigurerSupport {
|
||||
|
||||
@ -744,7 +831,7 @@ public class CacheAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
@Import({GenericCacheConfiguration.class, RedisCacheConfiguration.class})
|
||||
static class CustomCacheResolverConfiguration extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@ -765,4 +852,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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.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(), containsInAnyOrder("one", "two"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@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"));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -3184,6 +3184,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`
|
||||
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]]
|
||||
|
Loading…
Reference in New Issue
Block a user