001/*
002 * Copyright 2002-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 *      https://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.cache.annotation;
018
019import java.util.Collection;
020import java.util.function.Supplier;
021
022import org.springframework.beans.factory.annotation.Autowired;
023import org.springframework.cache.CacheManager;
024import org.springframework.cache.interceptor.CacheErrorHandler;
025import org.springframework.cache.interceptor.CacheResolver;
026import org.springframework.cache.interceptor.KeyGenerator;
027import org.springframework.context.annotation.Configuration;
028import org.springframework.context.annotation.ImportAware;
029import org.springframework.core.annotation.AnnotationAttributes;
030import org.springframework.core.type.AnnotationMetadata;
031import org.springframework.lang.Nullable;
032import org.springframework.util.CollectionUtils;
033
034/**
035 * Abstract base {@code @Configuration} class providing common structure
036 * for enabling Spring's annotation-driven cache management capability.
037 *
038 * @author Chris Beams
039 * @author Stephane Nicoll
040 * @author Juergen Hoeller
041 * @since 3.1
042 * @see EnableCaching
043 */
044@Configuration
045public abstract class AbstractCachingConfiguration implements ImportAware {
046
047        @Nullable
048        protected AnnotationAttributes enableCaching;
049
050        @Nullable
051        protected Supplier<CacheManager> cacheManager;
052
053        @Nullable
054        protected Supplier<CacheResolver> cacheResolver;
055
056        @Nullable
057        protected Supplier<KeyGenerator> keyGenerator;
058
059        @Nullable
060        protected Supplier<CacheErrorHandler> errorHandler;
061
062
063        @Override
064        public void setImportMetadata(AnnotationMetadata importMetadata) {
065                this.enableCaching = AnnotationAttributes.fromMap(
066                                importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
067                if (this.enableCaching == null) {
068                        throw new IllegalArgumentException(
069                                        "@EnableCaching is not present on importing class " + importMetadata.getClassName());
070                }
071        }
072
073        @Autowired(required = false)
074        void setConfigurers(Collection<CachingConfigurer> configurers) {
075                if (CollectionUtils.isEmpty(configurers)) {
076                        return;
077                }
078                if (configurers.size() > 1) {
079                        throw new IllegalStateException(configurers.size() + " implementations of " +
080                                        "CachingConfigurer were found when only 1 was expected. " +
081                                        "Refactor the configuration such that CachingConfigurer is " +
082                                        "implemented only once or not at all.");
083                }
084                CachingConfigurer configurer = configurers.iterator().next();
085                useCachingConfigurer(configurer);
086        }
087
088        /**
089         * Extract the configuration from the nominated {@link CachingConfigurer}.
090         */
091        protected void useCachingConfigurer(CachingConfigurer config) {
092                this.cacheManager = config::cacheManager;
093                this.cacheResolver = config::cacheResolver;
094                this.keyGenerator = config::keyGenerator;
095                this.errorHandler = config::errorHandler;
096        }
097
098}