20220308_spring@EnableCaching注解源码分析学习笔记.md
1概述
1.1涉及知识点
- EnableCaching启动入口
- AnnotationAwareAspectJAutoProxyCreator(本质BeanPostProcessor)的构建过程
- 普通Bean(UserController)一步步演变成代理对象的细节分析
1.2源码分析
1.2.1EnableCaching启动入口
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;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({CachingConfigurationSelector.class})
public @interface EnableCaching {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
1.2.1.1CachingConfigurationSelector
public class CachingConfigurationSelector extends AdviceModeImportSelector {
如果adviceMode:PROXY,则将类AutoProxyRegistrar、ProxyCachingConfiguration添加到Imports数组中。
1.2.1.1.1AutoProxyRegistrar创建bpp元数据
AutoProxyRegistrar功能,负责创建RootBeanDefinition,并注入到registry容器,后续会创建Bean对象,名称为:AnnotationAwareAspectJAutoProxyCreator(实际就是一个BeanPostProcessor),内置BeanFactoryCacheOperationSourceAdvisor的配置。
注意,低版本可能为:InfrastructureAdvisorAutoProxyCreator。
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
public abstract class AopConfigUtils {
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
/**
* The bean name of the internally managed auto-proxy creator.
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // 2:ROLE_INFRASTRUCTURE
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
public InfrastructureAdvisorAutoProxyCreator() {
}
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Nullable
private List includePatterns;
@Nullable
private AspectJAdvisorFactory aspectJAdvisorFactory;
@Nullable
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
public AnnotationAwareAspectJAutoProxyCreator() {
}
1.2.1.1.2ProxyCachingConfiguration代理配置类
/**
* The name of the cache advisor bean.
*/
public static final String CACHE_ADVISOR_BEAN_NAME =
"org.springframework.cache.config.internalCacheAdvisor";
// 注入切面
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {
// 注解解析器:AnnotationCacheOperationSource
return new AnnotationCacheOperationSource();
}
public AnnotationCacheOperationSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
// 这里内置了注解解析器:SpringCacheAnnotationParser
this.annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
}
public class SpringCacheAnnotationParser implements CacheAnnotationParser, Serializable {
private static final Set> CACHE_OPERATION_ANNOTATIONS = new LinkedHashSet<>(8);
static { // 支持的解析注解
CACHE_OPERATION_ANNOTATIONS.add(Cacheable.class);
CACHE_OPERATION_ANNOTATIONS.add(CacheEvict.class);
CACHE_OPERATION_ANNOTATIONS.add(CachePut.class);
CACHE_OPERATION_ANNOTATIONS.add(Caching.class);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {
1.2.2AnnotationAwareAspectJAutoProxyCreator(本质BeanPostProcessor)的构建过程
// AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
// Register bean processors that intercept bean creation.
// Eg:org.springframework.aop.config.internalAutoProxyCreator
// 最终生成bpp:AnnotationAwareAspectJAutoProxyCreator(本质BeanPostProcessor)
registerBeanPostProcessors(beanFactory);
1.2.3普通Bean(UserController)一步步演变成代理对象的细节分析
1.2.3.1我们知道spring创建一个Bean的三部曲如下:
AbstractAutowireCapableBeanFactory.class:
// 1.bean实例化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 2.属性填充
populateBean(beanName, mbd, instanceWrapper);A
// 3.初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 3.1
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 3.2.
invokeInitMethods(beanName, wrappedBean, mbd);
// 3.3重点在这儿
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
1.2.3.2applyBeanPostProcessorsAfterInitialization
如果发现该Bean的方法存在上述4个注解定义时,会对该类套一层缓存代理。
// 这里遍历所有的bpp,并调用bpp中的方法:postProcessAfterInitialization
// 我们重点关注:AnnotationAwareAspectJAutoProxyCreator 这个bpp
// existingBean:原生Bean
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
InfrastructureAdvisorAutoProxyCreator这个bpp,执行流程:
BeanFactoryCacheOperationSourceAdvisor
实例,继承了Advisor
接口,在获取后续的Bean时,会对这些Bean Bean.getDeclaredMethods
方法清单里的每个方法,调用matches
进行检测:
// BeanFactoryCacheOperationSourceAdvisor的private属性CacheOperationSourcePointcut 里的方法
@Override
public boolean matches(Method method, Class> targetClass) {
CacheOperationSource cas = getCacheOperationSource();
return (cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass)));
}
这个cas就是ProxyCachingConfiguration里的AnnotationCacheOperationSource实例,通过cas.getCacheOperations方法,
调用org.springframework.cache.annotation.SpringCacheAnnotationParser类的方法parseCacheAnnotations,
读取Bean的方法上的Cacheable、CacheEvict、CachePut、Caching这4个注解定义,并转成 CacheOperation,然后缓存起来.
如果发现该Bean的方法存在上述4个注解定义时,会对该类套一层缓存代理,每次调用缓存方法,都会被 BeanFactoryCacheOperationSourceAdvisor.getAdvice()所拦截,这个getAdvice方法返回的就是上面ProxyCachingConfiguration里的CacheInterceptor实例。
2实验代码
2.1MyCacheConfig
@Configuration
@EnableCaching
public class MyCacheConfig {
}
2.2UserController
@RestController
public class UserController {
@RequestMapping(value = "updateUserInfo", method = {RequestMethod.GET, RequestMethod.POST})
// 当需要在不影响方法执行的情况下更新缓存时,可以使用 @CachePut,也就是说,被 @CachePut 注解的缓存方法总是会执行
// 表示对key=kikop的数据进行更新
@CachePut
@ResponseBody
public JSONObject updateUserInfo(@RequestBody JSONObject reqParam) {
return null;
}
}
2总结
2.1@CachePut和@Cacheable的区别
@CachePut负责增加缓存
@Cacheable负责查询缓存,如果没查到,则将执行方法,并将方法的结果增加到缓存
由于与 @Cacheable 的属性基本相同,所以不再重复示例。这里重点说明一下它们的区别:
@Cacheable 的逻辑是:查找缓存 - 有就返回 -没有就执行方法体 - 将结果缓存起来;
@CachePut 的逻辑是:执行方法体 - 将结果缓存起来;
所以 @Cacheable 适用于查询数据的方法,@CachePut 适用于更新数据的方法。
参考
1.1springboot2.0 redis EnableCaching的配置和使用
http://www.javashuo.com/article/p-docwscfv-dh.html
1.2Spring boot 下redis缓存的使用@EnableCaching、@CacheConfig、@Cacheable、@CacheEvict、@CachePut
https://blog.csdn.net/weixin_42404323/article/details/94722161?spm=1001.2014.3001.5506
1.3Spring框架的Cache缓存实现源码解读与原理解析
https://blog.csdn.net/youbl/article/details/112573887?spm=1001.2014.3001.5506
1.4spring cache 学习——@CachePut 使用详解
https://www.cnblogs.com/coding-one/p/12403801.html