org.springframework.cache.annotation.EnableCaching Maven / Gradle / Ivy
/*
* Copyright 2002-2024 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
*
* https://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 } XML namespace. To be used together
* with @{@link org.springframework.context.annotation.Configuration Configuration}
* classes as follows:
*
*
* @Configuration
* @EnableCaching
* class AppConfig {
*
* @Bean
* MyService myService() {
* // configure and return a class having @Cacheable methods
* return new MyService();
* }
*
* @Bean
* CacheManager cacheManager() {
* // configure and return an implementation of Spring's CacheManager SPI
* SimpleCacheManager cacheManager = new SimpleCacheManager();
* cacheManager.setCaches(Set.of(new ConcurrentMapCache("default")));
* return cacheManager;
* }
* }
*
* For reference, the example above can be compared to the following Spring XML
* configuration:
*
*
* <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>
*
*
* In both of the scenarios above, {@code @EnableCaching} and {@code
* } 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.
*
* 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.
*
*
A bean of type {@link org.springframework.cache.CacheManager CacheManager}
* must be registered, as there is no reasonable default that the framework can
* use as a convention. And whereas the {@code } element assumes
* a bean named "cacheManager", {@code @EnableCaching} searches for a cache
* manager bean by type. Therefore, naming of the cache manager bean method is
* not significant.
*
* 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:
*
*
* @Configuration
* @EnableCaching
* class AppConfig implements CachingConfigurer {
*
* @Bean
* MyService myService() {
* // configure and return a class having @Cacheable methods
* return new MyService();
* }
*
* @Bean
* @Override
* CacheManager cacheManager() {
* // configure and return an implementation of Spring's CacheManager SPI
* SimpleCacheManager cacheManager = new SimpleCacheManager();
* cacheManager.setCaches(Set.of(new ConcurrentMapCache("default")));
* return cacheManager;
* }
*
* @Override
* KeyGenerator keyGenerator() {
* // configure and return an implementation of Spring's KeyGenerator SPI
* return new MyKeyGenerator();
* }
* }
*
* 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.
*
* 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 custom key
* generator can be specified.
*
*
{@link CachingConfigurer} offers additional customization options:
* see the {@link CachingConfigurer} javadoc for further details.
*
*
The {@link #mode} attribute controls how advice is applied: If the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
* of the proxying. Please note that proxy mode allows for interception of calls through
* the proxy only; local calls within the same class cannot get intercepted that way.
*
*
Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
* value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
* this case the {@code spring-aspects} module JAR must be present on the classpath, with
* compile-time weaving or load-time weaving applying the aspect to the affected classes.
* There is no proxy involved in such a scenario; local calls will be intercepted as well.
*
* @author Chris Beams
* @author Juergen Hoeller
* @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}.
* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}.
*
Note that setting this attribute to {@code true} will affect all
* 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,
* for example, in tests.
*/
boolean proxyTargetClass() default false;
/**
* Indicate how caching advice should be applied.
*
The default is {@link AdviceMode#PROXY}.
* Please note that proxy mode allows for interception of calls through the proxy
* only. Local calls within the same class cannot get intercepted that way;
* a caching annotation on such a method within a local call will be ignored
* since Spring's interceptor does not even kick in for such a runtime scenario.
* For a more advanced mode of interception, consider switching this to
* {@link AdviceMode#ASPECTJ}.
*/
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;
}