/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.cache.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.AdviceMode; import org.springframework.context.annotation.Import; import org.springframework.core.Ordered; /** * Enables Spring's annotation-driven cache management capability, similar to the * support found in Spring's {@code <cache:*>} XML namespace. To be used together * with @{@link org.springframework.context.annotation.Configuration Configuration} * classes as follows: * * <pre class="code"> * @Configuration * @EnableCaching * public class AppConfig { * * @Bean * public MyService myService() { * // configure and return a class having @Cacheable methods * return new MyService(); * } * * @Bean * public CacheManager cacheManager() { * // configure and return an implementation of Spring's CacheManager SPI * SimpleCacheManager cacheManager = new SimpleCacheManager(); * cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("default"))); * return cacheManager; * } * }</pre> * * <p>For reference, the example above can be compared to the following Spring XML * configuration: * * <pre class="code"> * {@code * <beans> * * <cache:annotation-driven/> * * <bean id="myService" class="com.foo.MyService"/> * * <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> * <property name="caches"> * <set> * <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"> * <property name="name" value="default"/> * </bean> * </set> * </property> * </bean> * * </beans> * }</pre> * * In both of the scenarios above, {@code @EnableCaching} and {@code * <cache:annotation-driven/>} are responsible for registering the necessary Spring * components that power annotation-driven cache management, such as the * {@link org.springframework.cache.interceptor.CacheInterceptor CacheInterceptor} and the * proxy- or AspectJ-based advice that weaves the interceptor into the call stack when * {@link org.springframework.cache.annotation.Cacheable @Cacheable} methods are invoked. * * <p>If the JSR-107 API and Spring's JCache implementation are present, the necessary * components to manage standard cache annotations are also registered. This creates the * proxy- or AspectJ-based advice that weaves the interceptor into the call stack when * methods annotated with {@code CacheResult}, {@code CachePut}, {@code CacheRemove} or * {@code CacheRemoveAll} are invoked. * * <p><strong>A bean of type {@link org.springframework.cache.CacheManager CacheManager} * must be registered</strong>, as there is no reasonable default that the framework can * use as a convention. And whereas the {@code <cache:annotation-driven>} element assumes * a bean <em>named</em> "cacheManager", {@code @EnableCaching} searches for a cache * manager bean <em>by type</em>. Therefore, naming of the cache manager bean method is * not significant. * * <p>For those that wish to establish a more direct relationship between * {@code @EnableCaching} and the exact cache manager bean to be used, * the {@link CachingConfigurer} callback interface may be implemented. * Notice the {@code @Override}-annotated methods below: * * <pre class="code"> * @Configuration * @EnableCaching * public class AppConfig extends CachingConfigurerSupport { * * @Bean * public MyService myService() { * // configure and return a class having @Cacheable methods * return new MyService(); * } * * @Bean * @Override * public CacheManager cacheManager() { * // configure and return an implementation of Spring's CacheManager SPI * SimpleCacheManager cacheManager = new SimpleCacheManager(); * cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("default"))); * return cacheManager; * } * * @Bean * @Override * public KeyGenerator keyGenerator() { * // configure and return an implementation of Spring's KeyGenerator SPI * return new MyKeyGenerator(); * } * }</pre> * * This approach may be desirable simply because it is more explicit, or it may be * necessary in order to distinguish between two {@code CacheManager} beans present in the * same container. * * <p>Notice also the {@code keyGenerator} method in the example above. This allows for * customizing the strategy for cache key generation, per Spring's {@link * org.springframework.cache.interceptor.KeyGenerator KeyGenerator} SPI. Normally, * {@code @EnableCaching} will configure Spring's * {@link org.springframework.cache.interceptor.SimpleKeyGenerator SimpleKeyGenerator} * for this purpose, but when implementing {@code CachingConfigurer}, a key generator * must be provided explicitly. Return {@code null} or {@code new SimpleKeyGenerator()} * from this method if no customization is necessary. * * <p>{@link CachingConfigurer} offers additional customization options: it is recommended * to extend from {@link org.springframework.cache.annotation.CachingConfigurerSupport * CachingConfigurerSupport} that provides a default implementation for all methods which * can be useful if you do not need to customize everything. See {@link CachingConfigurer} * Javadoc for further details. * * <p>The {@link #mode()} attribute controls how advice is applied; if the mode is * {@link AdviceMode#PROXY} (the default), then the other attributes such as * {@link #proxyTargetClass()} control the behavior of the proxying. * * <p>If the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the * {@link #proxyTargetClass()} attribute is obsolete. Note also that in this case the * {@code spring-aspects} module JAR must be present on the classpath. * * @author Chris Beams * @since 3.1 * @see CachingConfigurer * @see CachingConfigurationSelector * @see ProxyCachingConfiguration * @see org.springframework.cache.aspectj.AspectJCachingConfiguration */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(CachingConfigurationSelector.class) public @interface EnableCaching { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. <strong> * Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>. * <p>Note that setting this attribute to {@code true} will affect <em>all</em> * Spring-managed beans requiring proxying, not just those marked with {@code @Cacheable}. * For example, other beans marked with Spring's {@code @Transactional} annotation will * be upgraded to subclass proxying at the same time. This approach has no negative * impact in practice unless one is explicitly expecting one type of proxy vs another, * e.g. in tests. */ boolean proxyTargetClass() default false; /** * Indicate how caching advice should be applied. The default is * {@link AdviceMode#PROXY}. * @see AdviceMode */ AdviceMode mode() default AdviceMode.PROXY; /** * Indicate the ordering of the execution of the caching advisor * when multiple advices are applied at a specific joinpoint. * The default is {@link Ordered#LOWEST_PRECEDENCE}. */ int order() default Ordered.LOWEST_PRECEDENCE; }