001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.cache; 018 019import java.util.stream.Collectors; 020 021import org.springframework.beans.factory.InitializingBean; 022import org.springframework.beans.factory.ObjectProvider; 023import org.springframework.boot.autoconfigure.AutoConfigureAfter; 024import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 025import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration.CacheConfigurationImportSelector; 026import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 027import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 028import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 029import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; 030import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor; 031import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; 032import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration; 033import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; 034import org.springframework.boot.context.properties.EnableConfigurationProperties; 035import org.springframework.cache.CacheManager; 036import org.springframework.cache.annotation.EnableCaching; 037import org.springframework.cache.interceptor.CacheAspectSupport; 038import org.springframework.context.annotation.Bean; 039import org.springframework.context.annotation.Configuration; 040import org.springframework.context.annotation.Import; 041import org.springframework.context.annotation.ImportSelector; 042import org.springframework.core.type.AnnotationMetadata; 043import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; 044import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 045import org.springframework.util.Assert; 046 047/** 048 * {@link EnableAutoConfiguration Auto-configuration} for the cache abstraction. Creates a 049 * {@link CacheManager} if necessary when caching is enabled via {@link EnableCaching}. 050 * <p> 051 * Cache store can be auto-detected or specified explicitly via configuration. 052 * 053 * @author Stephane Nicoll 054 * @since 1.3.0 055 * @see EnableCaching 056 */ 057@Configuration 058@ConditionalOnClass(CacheManager.class) 059@ConditionalOnBean(CacheAspectSupport.class) 060@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver") 061@EnableConfigurationProperties(CacheProperties.class) 062@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class, 063 HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class }) 064@Import(CacheConfigurationImportSelector.class) 065public class CacheAutoConfiguration { 066 067 @Bean 068 @ConditionalOnMissingBean 069 public CacheManagerCustomizers cacheManagerCustomizers( 070 ObjectProvider<CacheManagerCustomizer<?>> customizers) { 071 return new CacheManagerCustomizers( 072 customizers.orderedStream().collect(Collectors.toList())); 073 } 074 075 @Bean 076 public CacheManagerValidator cacheAutoConfigurationValidator( 077 CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) { 078 return new CacheManagerValidator(cacheProperties, cacheManager); 079 } 080 081 @Configuration 082 @ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class) 083 @ConditionalOnBean(AbstractEntityManagerFactoryBean.class) 084 protected static class CacheManagerJpaDependencyConfiguration 085 extends EntityManagerFactoryDependsOnPostProcessor { 086 087 public CacheManagerJpaDependencyConfiguration() { 088 super("cacheManager"); 089 } 090 091 } 092 093 /** 094 * Bean used to validate that a CacheManager exists and provide a more meaningful 095 * exception. 096 */ 097 static class CacheManagerValidator implements InitializingBean { 098 099 private final CacheProperties cacheProperties; 100 101 private final ObjectProvider<CacheManager> cacheManager; 102 103 CacheManagerValidator(CacheProperties cacheProperties, 104 ObjectProvider<CacheManager> cacheManager) { 105 this.cacheProperties = cacheProperties; 106 this.cacheManager = cacheManager; 107 } 108 109 @Override 110 public void afterPropertiesSet() { 111 Assert.notNull(this.cacheManager.getIfAvailable(), 112 () -> "No cache manager could " 113 + "be auto-configured, check your configuration (caching " 114 + "type is '" + this.cacheProperties.getType() + "')"); 115 } 116 117 } 118 119 /** 120 * {@link ImportSelector} to add {@link CacheType} configuration classes. 121 */ 122 static class CacheConfigurationImportSelector implements ImportSelector { 123 124 @Override 125 public String[] selectImports(AnnotationMetadata importingClassMetadata) { 126 CacheType[] types = CacheType.values(); 127 String[] imports = new String[types.length]; 128 for (int i = 0; i < types.length; i++) { 129 imports[i] = CacheConfigurations.getConfigurationClass(types[i]); 130 } 131 return imports; 132 } 133 134 } 135 136}