Add cache manager auto-configuration
Add support for cache manager auto-configuration that is triggered when the `EnableCaching` annotation is added to a Spring Boot application. A new "spring.cache" set of configuration keys is also provided. The "spring.cache.mode" allows the user to specify the cache provider that should be auto-configured. If no explicit configuration is provided, the environment is checked for the best suited cache implementation, that is: - Generic if at least one `Cache` bean is defined in the context. - Hazelcast if either a default configuration file is present or the `spring.cache.config` property is set. - JCache if one JSR-107 provider is present - Redis if a `RedisTemplate` is defined in the context - Guava - Simple as a fallback option, using concurrent maps - NoOp (that is, no cache) if the mode is set to "none" If the provider supports it, it is possible to specify the caches to create on startup via `spring.cache.cache-names`. If the provider relies on a configuration file and a custom one needs to be used `spring.cache.config` can be set to such custom resource. If more than one JSR-107 provider is present, it is possible to force the provider to use by setting the mode to `jcache` and specifying the fully qualified class name of the CachingProvider to use via `spring.cache.jcache.provider`. See gh-2633pull/1784/head
parent
10da3d390e
commit
151220f41d
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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 javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration.CacheConfigurationImportSelector;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.CacheAspectSupport;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for the cache abstraction. Creates a
|
||||
* {@link CacheManager} if necessary when caching is enabled via {@link EnableCaching}.
|
||||
* <p>
|
||||
* Cache store can be auto-detected or specified explicitly via configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
* @see EnableCaching
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(CacheManager.class)
|
||||
@ConditionalOnBean(CacheAspectSupport.class)
|
||||
@ConditionalOnMissingBean({ CacheManager.class, CacheResolver.class })
|
||||
@EnableConfigurationProperties(CacheProperties.class)
|
||||
@AutoConfigureAfter(RedisAutoConfiguration.class)
|
||||
@Import(CacheConfigurationImportSelector.class)
|
||||
public class CacheAutoConfiguration {
|
||||
|
||||
static final String VALIDATOR_BEAN_NAME = "cacheAutoConfigurationValidator";
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public static BeanFactoryPostProcessor cacheAutoConfigurationValidatorPostProcessor() {
|
||||
return new CacheManagerValidatorPostProcessor();
|
||||
}
|
||||
|
||||
@Bean(name = VALIDATOR_BEAN_NAME)
|
||||
public CacheManagerValidator cacheAutoConfigurationValidator() {
|
||||
return new CacheManagerValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanFactoryPostProcessor} to ensure that the {@link CacheManagerValidator}
|
||||
* is triggered before {@link CacheAspectSupport} but without causing early
|
||||
* instantiation.
|
||||
*/
|
||||
static class CacheManagerValidatorPostProcessor implements BeanFactoryPostProcessor {
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
for (String name : beanFactory.getBeanNamesForType(CacheAspectSupport.class)) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(name);
|
||||
definition.setDependsOn(append(definition.getDependsOn(),
|
||||
VALIDATOR_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
private String[] append(String[] array, String value) {
|
||||
String[] result = new String[array == null ? 1 : array.length + 1];
|
||||
if (array != null) {
|
||||
System.arraycopy(array, 0, result, 0, array.length);
|
||||
}
|
||||
result[result.length - 1] = value;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean used to validate that a CacheManager exists and provide a more meaningful
|
||||
* exception.
|
||||
*/
|
||||
static class CacheManagerValidator {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheManager beanFactory;
|
||||
|
||||
@PostConstruct
|
||||
public void checkHasCacheManager() {
|
||||
Assert.notNull(this.beanFactory, "No cache manager could "
|
||||
+ "be auto-configured, check your configuration (caching "
|
||||
+ "type is '" + this.cacheProperties.getType() + "')");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ImportSelector} to add {@link CacheType} configuration classes.
|
||||
*/
|
||||
static class CacheConfigurationImportSelector implements ImportSelector {
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
CacheType[] types = CacheType.values();
|
||||
String[] imports = new String[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
imports[i] = types[i].getConfigurationClass().getName();
|
||||
}
|
||||
return imports;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* General cache condition used with all cache configuration classes.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
class CacheCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "spring.cache.");
|
||||
if (!resolver.containsProperty("type")) {
|
||||
return ConditionOutcome.match("Automatic cache type");
|
||||
}
|
||||
CacheType cacheType = CacheType
|
||||
.forConfigurationClass(((AnnotationMetadata) metadata).getClassName());
|
||||
String value = resolver.getProperty("type").replace("-", "_").toUpperCase();
|
||||
if (value.equals(cacheType.name())) {
|
||||
return ConditionOutcome.match("Cache type " + cacheType);
|
||||
}
|
||||
return ConditionOutcome.noMatch("Cache type " + value);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* {@link SpringBootCondition} used to check if a cache configuration file can be found.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
abstract class CacheConfigFileCondition extends SpringBootCondition {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String[] resourceLocations;
|
||||
|
||||
public CacheConfigFileCondition(String name, String... resourceLocations) {
|
||||
this.name = name;
|
||||
this.resourceLocations = resourceLocations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "spring.cache.");
|
||||
if (resolver.containsProperty("config")) {
|
||||
return ConditionOutcome.match("A spring.cache.config property is specified");
|
||||
}
|
||||
return getResourceOutcome(context, metadata);
|
||||
}
|
||||
|
||||
protected ConditionOutcome getResourceOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
for (String location : this.resourceLocations) {
|
||||
Resource resource = context.getResourceLoader().getResource(location);
|
||||
if (resource != null && resource.exists()) {
|
||||
return ConditionOutcome.match("Found " + this.name + " config in "
|
||||
+ resource);
|
||||
}
|
||||
}
|
||||
return ConditionOutcome.noMatch("No specific " + this.name
|
||||
+ " configuration found");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configuration properties for the cache abstraction.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.cache")
|
||||
public class CacheProperties {
|
||||
|
||||
/**
|
||||
* Cache type, auto-detected according to the environment by default.
|
||||
*/
|
||||
private CacheType type;
|
||||
|
||||
/**
|
||||
* The location of the configuration file to use to initialize the cache library.
|
||||
*/
|
||||
private Resource config;
|
||||
|
||||
/**
|
||||
* Comma-separated list of cache names to create if supported by the underlying cache
|
||||
* manager. Usually, this disables the ability to create additional caches on-the-fly.
|
||||
*/
|
||||
private final List<String> cacheNames = new ArrayList<String>();
|
||||
|
||||
private final JCache jcache = new JCache();
|
||||
|
||||
private final Guava guava = new Guava();
|
||||
|
||||
public CacheType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(CacheType mode) {
|
||||
this.type = mode;
|
||||
}
|
||||
|
||||
public Resource getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public void setConfig(Resource config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public List<String> getCacheNames() {
|
||||
return this.cacheNames;
|
||||
}
|
||||
|
||||
public JCache getJcache() {
|
||||
return this.jcache;
|
||||
}
|
||||
|
||||
public Guava getGuava() {
|
||||
return this.guava;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the config location if set.
|
||||
* @return the location or {@code null} if it is not set
|
||||
* @throws IllegalArgumentException if the config attribute is set to a unknown
|
||||
* location
|
||||
*/
|
||||
public Resource resolveConfigLocation() {
|
||||
if (this.config != null) {
|
||||
Assert.isTrue(this.config.exists(), "Cache configuration field defined by "
|
||||
+ "'spring.cache.config' does not exist " + this.config);
|
||||
return this.config;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* JCache (JSR-107) specific cache properties.
|
||||
*/
|
||||
public static class JCache {
|
||||
|
||||
/**
|
||||
* Fully qualified name of the CachingProvider implementation to use to retrieve
|
||||
* the JSR-107 compliant cache manager. Only needed if more than one JSR-107
|
||||
* implementation is available on the classpath.
|
||||
*/
|
||||
private String provider;
|
||||
|
||||
public String getProvider() {
|
||||
return this.provider;
|
||||
}
|
||||
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Guava specific cache properties.
|
||||
*/
|
||||
public static class Guava {
|
||||
|
||||
/**
|
||||
* The spec to use to create caches. Check CacheBuilderSpec for more details on
|
||||
* the spec format.
|
||||
*/
|
||||
private String spec;
|
||||
|
||||
public String getSpec() {
|
||||
return this.spec;
|
||||
}
|
||||
|
||||
public void setSpec(String spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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;
|
||||
|
||||
/**
|
||||
* Supported cache types (defined in order of precedence).
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public enum CacheType {
|
||||
|
||||
/**
|
||||
* Generic caching using 'Cache 'beans from the context.
|
||||
*/
|
||||
GENERIC(GenericCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* Haezelcast backed caching
|
||||
*/
|
||||
HAZELCAST(HazelcastCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* JCache (JSR-107) backed caching.
|
||||
*/
|
||||
JCACHE(JCacheCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* Redis backed caching.
|
||||
*/
|
||||
REDIS(RedisCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* Guava backed caching.
|
||||
*/
|
||||
GUAVA(GuavaCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* Simple in-memory caching.
|
||||
*/
|
||||
SIMPLE(SimpleCacheConfiguration.class),
|
||||
|
||||
/**
|
||||
* No caching.
|
||||
*/
|
||||
NONE(NoOpCacheConfiguration.class);
|
||||
|
||||
private final Class<?> configurationClass;
|
||||
|
||||
CacheType(Class<?> configurationClass) {
|
||||
this.configurationClass = configurationClass;
|
||||
}
|
||||
|
||||
Class<?> getConfigurationClass() {
|
||||
return this.configurationClass;
|
||||
}
|
||||
|
||||
static CacheType forConfigurationClass(String configurationClass) {
|
||||
for (CacheType type : values()) {
|
||||
if (type.getConfigurationClass().getName().equals(configurationClass)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported class " + configurationClass);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.Collection;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Generic cache configuration based on arbitrary {@link Cache} instances defined in the
|
||||
* context.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(Cache.class)
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional(CacheCondition.class)
|
||||
class GenericCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
public SimpleCacheManager cacheManager(Collection<Cache> caches) {
|
||||
SimpleCacheManager cacheManager = new SimpleCacheManager();
|
||||
cacheManager.setCaches(caches);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.List;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.guava.GuavaCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheBuilderSpec;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
|
||||
/**
|
||||
* Guava cache configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(CacheBuilder.class)
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional(CacheCondition.class)
|
||||
class GuavaCacheConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheBuilder<Object, Object> cacheBuilder;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheBuilderSpec cacheBuilderSpec;
|
||||
|
||||
@Autowired(required = false)
|
||||
private CacheLoader<Object, Object> cacheLoader;
|
||||
|
||||
@Bean
|
||||
public GuavaCacheManager cacheManager() {
|
||||
GuavaCacheManager cacheManager = createCacheManager();
|
||||
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
||||
if (!CollectionUtils.isEmpty(cacheNames)) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
private GuavaCacheManager createCacheManager() {
|
||||
GuavaCacheManager cacheManager = new GuavaCacheManager();
|
||||
setCacheBuilder(cacheManager);
|
||||
if (this.cacheLoader != null) {
|
||||
cacheManager.setCacheLoader(this.cacheLoader);
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
private void setCacheBuilder(GuavaCacheManager cacheManager) {
|
||||
String specification = this.cacheProperties.getGuava().getSpec();
|
||||
if (StringUtils.hasText(specification)) {
|
||||
cacheManager.setCacheSpecification(specification);
|
||||
}
|
||||
else if (this.cacheBuilderSpec != null) {
|
||||
cacheManager.setCacheBuilderSpec(this.cacheBuilderSpec);
|
||||
}
|
||||
else if (this.cacheBuilder != null) {
|
||||
cacheManager.setCacheBuilder(this.cacheBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.XmlConfigBuilder;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.spring.cache.HazelcastCacheManager;
|
||||
|
||||
/**
|
||||
* Hazelcast cache configuration. Only kick in if a configuration file location is set or
|
||||
* if a default configuration file exists (either placed in the default location or set
|
||||
* via the {@value #CONFIG_SYSTEM_PROPERTY} system property).
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ HazelcastInstance.class, HazelcastCacheManager.class })
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional({ CacheCondition.class,
|
||||
HazelcastCacheConfiguration.ConfigAvailableCondition.class })
|
||||
class HazelcastCacheConfiguration {
|
||||
|
||||
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.config";
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Bean
|
||||
public HazelcastCacheManager cacheManager() throws IOException {
|
||||
return new HazelcastCacheManager(createHazelcastInstance());
|
||||
}
|
||||
|
||||
private HazelcastInstance createHazelcastInstance() throws IOException {
|
||||
Resource location = this.cacheProperties.resolveConfigLocation();
|
||||
if (location != null) {
|
||||
Config cfg = new XmlConfigBuilder(location.getURL()).build();
|
||||
return Hazelcast.newHazelcastInstance(cfg);
|
||||
}
|
||||
return Hazelcast.newHazelcastInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Hazelcast configuration is available. This either kick in if a
|
||||
* default configuration has been found or if property referring to the file to use
|
||||
* has been set.
|
||||
*/
|
||||
static class ConfigAvailableCondition extends CacheConfigFileCondition {
|
||||
|
||||
public ConfigAvailableCondition() {
|
||||
super("Hazelcast", "file:./hazelcast.xml", "classpath:/hazelcast.xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConditionOutcome getResourceOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
if (System.getProperty(CONFIG_SYSTEM_PROPERTY) != null) {
|
||||
return ConditionOutcome.match("System property '"
|
||||
+ CONFIG_SYSTEM_PROPERTY + "' is set.");
|
||||
}
|
||||
return super.getResourceOutcome(context, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.cache.CacheManager;
|
||||
import javax.cache.Caching;
|
||||
import javax.cache.configuration.MutableConfiguration;
|
||||
import javax.cache.spi.CachingProvider;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.cache.jcache.JCacheCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Cache configuration for JSR-107 compliant providers.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(Caching.class)
|
||||
@ConditionalOnMissingBean(org.springframework.cache.CacheManager.class)
|
||||
@Conditional({ CacheCondition.class,
|
||||
JCacheCacheConfiguration.JCacheAvailableCondition.class })
|
||||
class JCacheCacheConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private javax.cache.configuration.Configuration<?, ?> defaultCacheConfiguration;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<JCacheManagerCustomizer> cacheManagerCustomizers;
|
||||
|
||||
@Bean
|
||||
public JCacheCacheManager cacheManager() {
|
||||
CacheManager cacheManager = createCacheManager(this.cacheProperties.getJcache()
|
||||
.getProvider());
|
||||
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
||||
if (!CollectionUtils.isEmpty(cacheNames)) {
|
||||
for (String cacheName : cacheNames) {
|
||||
cacheManager.createCache(cacheName, getDefaultCacheConfiguration());
|
||||
}
|
||||
}
|
||||
customize(cacheManager);
|
||||
return new JCacheCacheManager(cacheManager);
|
||||
}
|
||||
|
||||
private CacheManager createCacheManager(String cachingProvider) {
|
||||
if (StringUtils.hasText(cachingProvider)) {
|
||||
return Caching.getCachingProvider(cachingProvider).getCacheManager();
|
||||
}
|
||||
return Caching.getCachingProvider().getCacheManager();
|
||||
}
|
||||
|
||||
private javax.cache.configuration.Configuration<?, ?> getDefaultCacheConfiguration() {
|
||||
if (this.defaultCacheConfiguration != null) {
|
||||
return this.defaultCacheConfiguration;
|
||||
}
|
||||
return new MutableConfiguration<Object, Object>();
|
||||
}
|
||||
|
||||
private void customize(CacheManager cacheManager) {
|
||||
if (this.cacheManagerCustomizers != null) {
|
||||
AnnotationAwareOrderComparator.sort(this.cacheManagerCustomizers);
|
||||
for (JCacheManagerCustomizer customizer : this.cacheManagerCustomizers) {
|
||||
customizer.customize(cacheManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if JCache is available. This either kick in if a default
|
||||
* {@link CachingProvider} has been found or if the property referring to the provider
|
||||
* to use has been set.
|
||||
*/
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
static class JCacheAvailableCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "spring.cache.jcache.");
|
||||
if (resolver.containsProperty("provider")) {
|
||||
return ConditionOutcome.match("JCache provider specified");
|
||||
}
|
||||
Iterator<CachingProvider> providers = Caching.getCachingProviders()
|
||||
.iterator();
|
||||
if (!providers.hasNext()) {
|
||||
return ConditionOutcome.noMatch("No JSR-107 compliant providers");
|
||||
}
|
||||
providers.next();
|
||||
if (providers.hasNext()) {
|
||||
return ConditionOutcome.noMatch("Multiple default JSR-107 compliant "
|
||||
+ "providers found");
|
||||
|
||||
}
|
||||
return ConditionOutcome.match("Default JSR-107 compliant provider found.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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 javax.cache.CacheManager;
|
||||
import javax.cache.configuration.Configuration;
|
||||
|
||||
/**
|
||||
* Callback interface that can be implemented by beans wishing to customize the cache
|
||||
* manager before it is used, in particular to create additional caches.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
* @see CacheManager#createCache(String, Configuration)
|
||||
*/
|
||||
public interface JCacheManagerCustomizer {
|
||||
|
||||
/**
|
||||
* Customize the cache manager.
|
||||
* @param cacheManager the {@link CacheManager} to customize
|
||||
*/
|
||||
void customize(CacheManager cacheManager);
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* No-op cache configuration used to disable caching via configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional(CacheCondition.class)
|
||||
class NoOpCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
public NoOpCacheManager cacheManager() {
|
||||
return new NoOpCacheManager();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.List;
|
||||
|
||||
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.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
/**
|
||||
* Redis cache configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(RedisTemplate.class)
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional(CacheCondition.class)
|
||||
class RedisCacheConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Bean
|
||||
public RedisCacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
|
||||
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
|
||||
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
||||
if (!cacheNames.isEmpty()) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Simplest cache configuration, usually used as a fallback.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(CacheManager.class)
|
||||
@Conditional(CacheCondition.class)
|
||||
class SimpleCacheConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
@Bean
|
||||
public ConcurrentMapCacheManager cacheManager() {
|
||||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
|
||||
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
||||
if (!cacheNames.isEmpty()) {
|
||||
cacheManager.setCacheNames(cacheNames);
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for the cache abstraction.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.cache;
|
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.cache.configuration.CompleteConfiguration;
|
||||
import javax.cache.configuration.MutableConfiguration;
|
||||
import javax.cache.expiry.CreatedExpiryPolicy;
|
||||
import javax.cache.expiry.Duration;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.cache.support.MockCachingProvider;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.cache.guava.GuavaCache;
|
||||
import org.springframework.cache.guava.GuavaCacheManager;
|
||||
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.jcache.JCacheCacheManager;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.hazelcast.cache.HazelcastCachingProvider;
|
||||
import com.hazelcast.spring.cache.HazelcastCacheManager;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link CacheAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class CacheAutoConfigurationTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noEnableCaching() {
|
||||
load(EmptyConfiguration.class);
|
||||
this.thrown.expect(NoSuchBeanDefinitionException.class);
|
||||
this.context.getBean(CacheManager.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheManagerBackOff() {
|
||||
load(CustomCacheManagerConfiguration.class);
|
||||
ConcurrentMapCacheManager cacheManager = validateCacheManager(ConcurrentMapCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), contains("custom1"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheManagerFromSupportBackOff() {
|
||||
load(CustomCacheManagerFromSupportConfiguration.class);
|
||||
ConcurrentMapCacheManager cacheManager = validateCacheManager(ConcurrentMapCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), contains("custom1"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheResolverBackOff() throws Exception {
|
||||
load(CustomCacheResolverConfiguration.class);
|
||||
this.thrown.expect(NoSuchBeanDefinitionException.class);
|
||||
this.context.getBean(CacheManager.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notSupportedCachingMode() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("cache");
|
||||
this.thrown.expectMessage("foobar");
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=foobar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleCacheExplicit() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=simple");
|
||||
ConcurrentMapCacheManager cacheManager = validateCacheManager(ConcurrentMapCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleCacheExplicitWithCacheNames() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=simple",
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
ConcurrentMapCacheManager cacheManager = validateCacheManager(ConcurrentMapCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericCacheWithCaches() {
|
||||
load(GenericCacheConfiguration.class);
|
||||
SimpleCacheManager cacheManager = validateCacheManager(SimpleCacheManager.class);
|
||||
assertThat(cacheManager.getCache("first"),
|
||||
equalTo(this.context.getBean("firstCache")));
|
||||
assertThat(cacheManager.getCache("second"),
|
||||
equalTo(this.context.getBean("secondCache")));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericCacheExplicit() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("No cache manager could be auto-configured");
|
||||
this.thrown.expectMessage("GENERIC");
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=generic");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void genericCacheExplicitWithCaches() {
|
||||
load(GenericCacheConfiguration.class, "spring.cache.type=generic");
|
||||
SimpleCacheManager cacheManager = validateCacheManager(SimpleCacheManager.class);
|
||||
assertThat(cacheManager.getCache("first"),
|
||||
equalTo(this.context.getBean("firstCache")));
|
||||
assertThat(cacheManager.getCache("second"),
|
||||
equalTo(this.context.getBean("secondCache")));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisCacheExplicit() {
|
||||
load(RedisCacheConfiguration.class, "spring.cache.type=redis");
|
||||
RedisCacheManager cacheManager = validateCacheManager(RedisCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisCacheExplicitWithCaches() {
|
||||
load(RedisCacheConfiguration.class, "spring.cache.type=redis",
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
RedisCacheManager cacheManager = validateCacheManager(RedisCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noOpCacheExplicit() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=none");
|
||||
NoOpCacheManager cacheManager = validateCacheManager(NoOpCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheNoProviderExplicit() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("No cache manager could be auto-configured");
|
||||
this.thrown.expectMessage("JCACHE");
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheWithProvider() {
|
||||
String cachingProviderFqn = MockCachingProvider.class.getName();
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + cachingProviderFqn);
|
||||
JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheWithCaches() {
|
||||
String cachingProviderFqn = MockCachingProvider.class.getName();
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + cachingProviderFqn,
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheWithCachesAndCustomConfig() {
|
||||
String cachingProviderFqn = MockCachingProvider.class.getName();
|
||||
load(JCacheCustomConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + cachingProviderFqn,
|
||||
"spring.cache.cacheNames[0]=one", "spring.cache.cacheNames[1]=two");
|
||||
JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("one", "two"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
|
||||
CompleteConfiguration<?, ?> defaultCacheConfiguration = this.context
|
||||
.getBean(CompleteConfiguration.class);
|
||||
verify(cacheManager.getCacheManager()).createCache("one",
|
||||
defaultCacheConfiguration);
|
||||
verify(cacheManager.getCacheManager()).createCache("two",
|
||||
defaultCacheConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheWithUnknownProvider() {
|
||||
String wrongCachingProviderFqn = "org.acme.FooBar";
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage(wrongCachingProviderFqn);
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + wrongCachingProviderFqn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastCacheExplicit() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast");
|
||||
HazelcastCacheManager cacheManager = validateCacheManager(HazelcastCacheManager.class);
|
||||
// NOTE: the hazelcast implementation know about a cache in a lazy manner.
|
||||
cacheManager.getCache("defaultCache");
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("defaultCache"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastCacheWithLocation() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
|
||||
"spring.cache.config=org/springframework/boot/autoconfigure/cache/hazelcast-specific.xml");
|
||||
HazelcastCacheManager cacheManager = validateCacheManager(HazelcastCacheManager.class);
|
||||
cacheManager.getCache("foobar");
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foobar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastWithWrongLocation() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("foo/bar/unknown.xml");
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
|
||||
"spring.cache.config=foo/bar/unknown.xml");
|
||||
System.out.println(this.context.getBean(CacheManager.class).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hazelcastAsJCacheWithCaches() {
|
||||
String cachingProviderFqn = HazelcastCachingProvider.class.getName();
|
||||
JCacheCacheManager cacheManager = null;
|
||||
try {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + cachingProviderFqn,
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
cacheManager = validateCacheManager(JCacheCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
finally {
|
||||
if (cacheManager != null) {
|
||||
cacheManager.getCacheManager().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jCacheCacheWithCachesAndCustomizer() {
|
||||
String cachingProviderFqn = HazelcastCachingProvider.class.getName();
|
||||
JCacheCacheManager cacheManager = null;
|
||||
try {
|
||||
load(JCacheWithCustomizerConfiguration.class, "spring.cache.type=jcache",
|
||||
"spring.cache.jcache.provider=" + cachingProviderFqn,
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
cacheManager = validateCacheManager(JCacheCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "custom1")); // see
|
||||
// customizer
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
}
|
||||
finally {
|
||||
if (cacheManager != null) {
|
||||
cacheManager.getCacheManager().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guavaCacheExplicitWithCaches() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=guava",
|
||||
"spring.cache.cacheNames=foo");
|
||||
GuavaCacheManager cacheManager = validateCacheManager(GuavaCacheManager.class);
|
||||
Cache foo = cacheManager.getCache("foo");
|
||||
foo.get("1");
|
||||
// See next tests: no spec given so stats should be disabled
|
||||
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount(), equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guavaCacheExplicitWithSpec() {
|
||||
load(DefaultCacheConfiguration.class, "spring.cache.type=guava",
|
||||
"spring.cache.guava.spec=recordStats", "spring.cache.cacheNames[0]=foo",
|
||||
"spring.cache.cacheNames[1]=bar");
|
||||
validateGuavaCacheWithStats();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guavaCacheExplicitWithCacheBuilder() {
|
||||
load(GuavaCacheBuilderConfiguration.class, "spring.cache.type=guava",
|
||||
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
|
||||
validateGuavaCacheWithStats();
|
||||
}
|
||||
|
||||
private void validateGuavaCacheWithStats() {
|
||||
GuavaCacheManager cacheManager = validateCacheManager(GuavaCacheManager.class);
|
||||
assertThat(cacheManager.getCacheNames(), containsInAnyOrder("foo", "bar"));
|
||||
assertThat(cacheManager.getCacheNames(), hasSize(2));
|
||||
Cache foo = cacheManager.getCache("foo");
|
||||
foo.get("1");
|
||||
assertThat(((GuavaCache) foo).getNativeCache().stats().missCount(), equalTo(1L));
|
||||
}
|
||||
|
||||
private <T extends CacheManager> T validateCacheManager(Class<T> type) {
|
||||
CacheManager cacheManager = this.context.getBean(CacheManager.class);
|
||||
assertThat("Wrong cache manager type", cacheManager, is(instanceOf(type)));
|
||||
return type.cast(cacheManager);
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
this.context = doLoad(config, environment);
|
||||
}
|
||||
|
||||
private AnnotationConfigApplicationContext doLoad(Class<?> config,
|
||||
String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
applicationContext.register(config);
|
||||
applicationContext.register(CacheAutoConfiguration.class);
|
||||
applicationContext.refresh();
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class DefaultCacheConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class GenericCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
public Cache firstCache() {
|
||||
return new ConcurrentMapCache("first");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Cache secondCache() {
|
||||
return new ConcurrentMapCache("second");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class RedisCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<?, ?> redisTemplate() {
|
||||
return mock(RedisTemplate.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class JCacheCustomConfiguration {
|
||||
|
||||
@Bean
|
||||
public CompleteConfiguration<?, ?> defaultCacheConfiguration() {
|
||||
return mock(CompleteConfiguration.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class JCacheWithCustomizerConfiguration {
|
||||
|
||||
@Bean
|
||||
JCacheManagerCustomizer myCustomizer() {
|
||||
return new JCacheManagerCustomizer() {
|
||||
@Override
|
||||
public void customize(javax.cache.CacheManager cacheManager) {
|
||||
MutableConfiguration<?, ?> config = new MutableConfiguration<Object, Object>();
|
||||
config.setExpiryPolicyFactory(CreatedExpiryPolicy
|
||||
.factoryOf(Duration.TEN_MINUTES));
|
||||
config.setStatisticsEnabled(true);
|
||||
cacheManager.createCache("custom1", config);
|
||||
cacheManager.destroyCache("bar");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
static class CustomCacheManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
return new ConcurrentMapCacheManager("custom1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
static class CustomCacheManagerFromSupportConfiguration extends
|
||||
CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
// The @Bean annotation is important, see CachingConfigurerSupport Javadoc
|
||||
public CacheManager cacheManager() {
|
||||
return new ConcurrentMapCacheManager("custom1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class GuavaCacheBuilderConfiguration {
|
||||
|
||||
@Bean
|
||||
CacheBuilder<Object, Object> cacheBuilder() {
|
||||
return CacheBuilder.newBuilder().recordStats();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ GenericCacheConfiguration.class, RedisCacheConfiguration.class })
|
||||
static class CustomCacheResolverConfiguration extends CachingConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
// The @Bean annotation is important, see CachingConfigurerSupport Javadoc
|
||||
public CacheResolver cacheResolver() {
|
||||
return new CacheResolver() {
|
||||
|
||||
@Override
|
||||
public Collection<? extends Cache> resolveCaches(
|
||||
CacheOperationInvocationContext<?> context) {
|
||||
return Collections.singleton(mock(Cache.class));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.support;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.cache.Cache;
|
||||
import javax.cache.CacheManager;
|
||||
import javax.cache.configuration.Configuration;
|
||||
import javax.cache.configuration.OptionalFeature;
|
||||
import javax.cache.spi.CachingProvider;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* A mock {@link CachingProvider} that exposes a JSR-107 cache manager for testing
|
||||
* purposes.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class MockCachingProvider implements CachingProvider {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public CacheManager getCacheManager(URI uri, ClassLoader classLoader,
|
||||
Properties properties) {
|
||||
CacheManager cacheManager = mock(CacheManager.class);
|
||||
final Map<String, Cache> caches = new HashMap<String, Cache>();
|
||||
given(cacheManager.getCacheNames()).willReturn(caches.keySet());
|
||||
given(cacheManager.getCache(anyString())).willAnswer(new Answer<Cache>() {
|
||||
@Override
|
||||
public Cache answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||
String cacheName = (String) invocationOnMock.getArguments()[0];
|
||||
return caches.get(cacheName);
|
||||
}
|
||||
});
|
||||
given(cacheManager.createCache(anyString(), any(Configuration.class))).will(
|
||||
new Answer<Cache>() {
|
||||
@Override
|
||||
public Cache answer(InvocationOnMock invocationOnMock)
|
||||
throws Throwable {
|
||||
String cacheName = (String) invocationOnMock.getArguments()[0];
|
||||
Cache cache = mock(Cache.class);
|
||||
given(cache.getName()).willReturn(cacheName);
|
||||
caches.put(cacheName, cache);
|
||||
return cache;
|
||||
}
|
||||
});
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getDefaultClassLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getDefaultURI() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getDefaultProperties() {
|
||||
return new Properties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheManager getCacheManager(URI uri, ClassLoader classLoader) {
|
||||
return getCacheManager(uri, classLoader, getDefaultProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheManager getCacheManager() {
|
||||
return getCacheManager(getDefaultURI(), getDefaultClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(ClassLoader classLoader) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(URI uri, ClassLoader classLoader) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(OptionalFeature optionalFeature) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
#
|
||||
# Test JSR 107 provider for testing purposes only.
|
||||
#
|
||||
org.springframework.boot.autoconfigure.cache.support.MockCachingProvider
|
@ -0,0 +1,8 @@
|
||||
<hazelcast
|
||||
xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
|
||||
xmlns="http://www.hazelcast.com/schema/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<map name="defaultCache" />
|
||||
|
||||
</hazelcast>
|
@ -0,0 +1,10 @@
|
||||
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
|
||||
xmlns="http://www.hazelcast.com/schema/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<map name="foobar">
|
||||
<time-to-live-seconds>3600</time-to-live-seconds>
|
||||
<max-idle-seconds>600</max-idle-seconds>
|
||||
</map>
|
||||
|
||||
</hazelcast>
|
Loading…
Reference in New Issue