diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index cb3bfab9db..fbadb64f89 100644
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -60,11 +60,26 @@
gsontrue
+
+ com.hazelcast
+ hazelcast
+ true
+
+
+ com.hazelcast
+ hazelcast-spring
+ true
+ com.samskivertjmustachetrue
+
+ javax.cache
+ cache-api
+ true
+ org.flywaydbflyway-core
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.java
new file mode 100644
index 0000000000..0dd37583c3
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.java
@@ -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}.
+ *
+ * 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;
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java
new file mode 100644
index 0000000000..77cdd4a5ce
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java
@@ -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);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigFileCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigFileCondition.java
new file mode 100644
index 0000000000..aa03c8cbbe
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigFileCondition.java
@@ -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");
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java
new file mode 100644
index 0000000000..c5aa4eb48d
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java
@@ -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 cacheNames = new ArrayList();
+
+ 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 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;
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java
new file mode 100644
index 0000000000..45ddaa4212
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java
@@ -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);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.java
new file mode 100644
index 0000000000..244122e2ef
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.java
@@ -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 caches) {
+ SimpleCacheManager cacheManager = new SimpleCacheManager();
+ cacheManager.setCaches(caches);
+ return cacheManager;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GuavaCacheConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GuavaCacheConfiguration.java
new file mode 100644
index 0000000000..f14c5f193f
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/GuavaCacheConfiguration.java
@@ -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