@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
}
// 导入其他类的一个bean
public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return getProxyImports() {
List<String> result = new ArrayList<>(3);
// 注册AutoProxyRegistrar和ProxyCachingConfiguration
result.add(. class.getName());
result.add(ProxyCachingConfiguration.class.getName());
if (jsr107Present && jcacheImplPresent) {
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
}
return StringUtils.toStringArray(result);
}
case ASPECTJ:
return getAspectJImports();
default:
return null;
}
}
}
// 负责注入创建AOP对象的BeanPostProcessor
// 事务注解也会注入的这类,它会负责注入创建代理对象的BeanPostProcessor
// 用来给目标类创建代理对象
class AutoProxyRegistrar {
// 注册Bean
// importingClassMetadata是正在解析的配置类对应的元数据信息,也就是标注@EnableTransactionManagement这个类的配置类
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取配置类上的所有注解
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
// 遍历所有的注解
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
// 找到一些符合AOP条件的共性,mode,proxyTargetClass等等
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
// 如果符合这个条件,表示当前类需要进行AOP
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
// 判断当前配置类的代理模式
if (mode == AdviceMode.PROXY) {
// 注册创建AOP代理对象的BeanPostProcessor,InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
// 如果proxyTargetClass为true,表示使用CGLIB代理
/*
三种情况
1. proxyTargetClass =false(默认值) 目标实现了接口 JDK代理
2. proxyTargetClass =false(默认值) 目标未实现接口 CGLIB代理
3. proxyTargetClass =true 总是CGLIB代理
*/
if ((Boolean) proxyTargetClass) {
// 强制设置创建代理的使用使用CGLIB代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
// 和事务的ProxyTransactionManagementConfiguration配置几乎类似
// 准确来说是需要创建代理对象的场景都需要下面配置,配置切面,拦截器,解析注解的数据源
class ProxyCachingConfiguration extends AbstractCachingConfiguration implements ImportAware {
// EnableCaching的元信息
protected AnnotationAttributes enableCaching;
// 缓存管理器
protected Supplier<CacheManager> cacheManager;
// 缓存解析器
protected Supplier<CacheResolver> cacheResolver;
// 缓存key的生成器
protected Supplier<KeyGenerator> keyGenerator;
// 缓存的异常处理器
protected Supplier<CacheErrorHandler> errorHandler;
public void setImportMetadata(AnnotationMetadata importMetadata) {
// 获取到EnableCaching注解的元信息
this.enableCaching = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
}
@Bean(name = "internalCacheAdvisor")
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
// 创建用于缓存的切面
BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor() {
// 缓存操作源的切面对象
// 切面内部的切点,是依靠CacheOperationSource来创建的
private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
protected CacheOperationSource getCacheOperationSource() {
// cacheOperationSource用来解析@CacheXXX属性源对象,内部封装了注解的元信息
return cacheOperationSource;
}
};
}
// 设置注解的操作元数据
advisor.setCacheOperationSource(cacheOperationSource());
// 设置通知,增强器,拦截器
advisor.setAdvice(cacheInterceptor());
// 如果开启了@EnableCaching注解
if (this.enableCaching != null) {
// 设置顺序
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
}
// 返回切面
return advisor;
}
// 处理注解CacheXXX注解的类
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource() {
// 是否只支持public方法,默认为true
this.publicMethodsOnly =publicMethodsOnly;
// 创建SpringCache的注解解析器
this.annotationParsers =Collections.singleton(new
SpringCacheAnnotationParser() {
// 注解解析器支持的注解类型
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() {
// 新建通知,拦截器
CacheInterceptor interceptor = new CacheInterceptor();
// 自定义配置拦截器
interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager) {
// 异常管理器,如果没有,给默认的
this.errorHandler = new SingletonSupplier<>(errorHandler, SimpleCacheErrorHandler::new);
// 缓存key生成器,如果没有,使用默认的
this.keyGenerator = new SingletonSupplier<>(keyGenerator, SimpleKeyGenerator::new);
// 缓存解析器,如果没有,
this.cacheResolver = new SingletonSupplier<>(cacheResolver, () -> SimpleCacheResolver.of(SupplierUtils.resolve(cacheManager)) {
return(cacheManager !=null?new
SimpleCacheResolver(cacheManager) :null);
});
}
// 设置注解的属性元信息
interceptor.setCacheOperationSource(cacheOperationSource());
// 返回拦截器
return interceptor;
}
}
// 通过AutoProxyRegistrar注入的,为了创建代理对象
class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
// 创建代理对象
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取缓存Key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 是否被提前引用,已经创建过代理对象了
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 创建代理对象,如果需要的话,具体的详见SpringAop原理,获取提前引用对象以及wrapIfNecessary是否需要创建代理对象原理
return wrapIfNecessary(bean, beanName, cacheKey) {
// 这里讲缓存相关代理的实现
// 获取到可以作用到Bean的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null) {
// 找到合格的切面
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName) {
// 从容器中找所有Advisor的切面,这个时候就可以找到上面注册的这个
// BeanFactoryCacheOperationSourceAdvisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 从所有的candidateAdvisors切面中,筛选作用于当前Bean的切面
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)
{
// 遍历所有的切面
for (Advisor candidate : candidateAdvisors) {
// 调用canApply
if (canApply(candidate, clazz, hasIntroductions) {
// BeanFactoryCacheOperationSourceAdvisor
// 这个切面就是切点类型的切面
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions) {
// 先通过切点中的类匹配器来对目标类进行校验
// 创建的是CacheOperationSourcePointcut切点
// private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
// protected CacheOperationSource getCacheOperationSource() {
// return cacheOperationSource;
// }
// };
// 创建切点的时候,设置了一个默认的类过滤器CacheOperationSourceClassFilter
// protected CacheOperationSourcePointcut() {
// setClassFilter(new CacheOperationSourceClassFilter());
// }
// 调用CacheOperationSourceClassFilter的matchs方法
if (!pc.getClassFilter().matches(targetClass) {
// bean为CacheManager,不处理
if (CacheManager.class.isAssignableFrom(clazz)) {
return false;
}
// 获取到缓存操作数据源,在注册BeanFactoryCacheOperationSourceAdvisor的Bean的时候设置了
// 为AnnotationCacheOperationSource
CacheOperationSource cas = getCacheOperationSource();
// 调用该类的校验方法
// isCandidateClass方法就是校验bean是否是Java内部的类,以及注解是不是java内部的注解
// 如果不是java内部的,统一返回true
return (cas == null || cas.isCandidateClass(clazz));
}){
// 类都匹配失败,就没必要匹配方法了
return false;
}
// 上面类型匹配成功,开始匹配方法,毕竟方法才能执行
// 获取的就是CacheOperationSourcePointcut切点本身
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
// 保存所有的类,因为类可能会实现接口,接口中又有默认方法
// 总之就是要校验所有类或者接口的所有方法
Set<Class<?>> classes = new LinkedHashSet<>();
// 如果不是jdk代理,将目标类也添加进去,因为jdk代理返回的是接口
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
// 在添加目标类实现的所有接口
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 遍历所有的类和接口
for (Class<?> clazz : classes) {
// 获取类中所有的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 调用方法匹配器的匹配方法
return methodMatcher.matches(method, targetClass)){
// 获取缓存操作的数据源
CacheOperationSource cas = getCacheOperationSource();
// 获取有没有缓存相关的注解信息
return (cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass)
{
// 获取缓存Key,防止重复操作
Object cacheKey = getCacheKey(method, targetClass);
// 获取是否操作过
Collection<CacheOperation> cached = this.attributeCache.get(cacheKey);
// 如果之前操作过,直接返回之前的结果
if (cached != null) {
return (cached != NULL_CACHING_ATTRIBUTE ? cached : null);
}
// 之前没有解析过缓存相关注解
else {
// 计算缓存操作,解析缓存注解信息
// 这里和事务注解逻辑几乎一样
Collection<CacheOperation> cacheOps = computeCacheOperations(method, targetClass)
{
// 如何设置了只允许public方法,但是方法又不是public,不处理
// allowPublicMethodsOnly默认为true
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// method是从外面传递过来的,要单独处理JDK动态代理
// specificMethod是被调用的类的方法对象,method可能是原始方法,CBLIB方法,也可能是接口的方法对象
// 例如:targetClass = B B impl A => B.test() 此时,specificMethod = B.test() , method = A.test()
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 第一次解析,解析正在处理的目标类中方法的缓存注解
Collection<CacheOperation> opDef = findCacheOperations(specificMethod)
{
// 解析缓存注解
CacheOperationProvider provider = parser -> parser.parseCacheAnnotations(method)
{
// 创建默认的缓存配置
DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass());
// 解析注解
return parseCacheAnnotations(defaultConfig, method)
{
// 正式解析注解
Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false)
{
// CACHE_OPERATION_ANNOTATIONS在静态代码块初始化了包含Cacheable,CacheEvict,CachePut,Caching
// 获取方法中存在的缓存相关的注解信息
Collection<? extends Annotation> anns = (localOnly ?
// 只会解析当前元素本身上的注解,例如接口上有注解,实现类中也有注解,此时只会返回元素本身的注解
AnnotatedElementUtils.getAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS) :
// 会考虑元素的继承,例如接口上有注解,实现类中也有注解,此时会返回两个注解
AnnotatedElementUtils.findAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS));
// 不存在,返回null
if (anns.isEmpty()) {
return null;
}
// 存在缓存注解
final Collection<CacheOperation> ops = new ArrayList<>(1);
// 过滤Cacheable注解,进行处理
anns.stream().filter(ann -> ann instanceof Cacheable).forEach(ann -> ops.add(parseCacheableAnnotation(ae, cachingConfig, (Cacheable) ann)
{
// 就是根据注解创建CacheableOperation对象,下面几个都一样
CacheableOperation.Builder builder = new CacheableOperation.Builder();
builder.setName(ae.toString());
builder.setCacheNames(cacheable.cacheNames());
builder.setSync(cacheable.sync());
CacheableOperation op = builder.build();
// 校验注解参数是否合法
validateCacheOperation(ae, op)
{
// KeyGenerator是bean的名称,会通过这个KeyGeneratorBean来生成缓存key,如果给定了key,又给定了生成器,抛出异常
if (StringUtils.hasText(operation.getKey()) && StringUtils.hasText(operation.getKeyGenerator())) {
throw new IllegalStateException("Invalid cache annotation configuration on '");
}
// 缓存管理器的bean与缓存解析器的bean也不能同时存在
if (StringUtils.hasText(operation.getCacheManager()) && StringUtils.hasText(operation.getCacheResolver())) {
throw new IllegalStateException("Invalid cache annotation configuration on '");
}
}
}));
// 过滤CacheEvict注解,进行处理
anns.stream().filter(ann -> ann instanceof CacheEvict).forEach(ann -> ops.add(parseEvictAnnotation(ae, cachingConfig, (CacheEvict) ann)));
// 过滤CachePut注解,进行处理
anns.stream().filter(ann -> ann instanceof CachePut).forEach(ann -> ops.add(parsePutAnnotation(ae, cachingConfig, (CachePut) ann)));
// 过滤Caching注解,进行处理
anns.stream().filter(ann -> ann instanceof Caching).forEach(ann -> parseCachingAnnotation(ae, cachingConfig, (Caching) ann, ops));
return ops;
}
// 如果解析到了缓存注解包装的CacheOperation信息,并且存在多个
// 表示可能类与接口中方法中都声明了相同缓存注解,所以存在多个
// 总之这里多次解析就是防止解析重复的注解
if (ops != null && ops.size() > 1) {
// 需要重新解析一遍,参数为true:表示直接解析当前Bean中的方法的注解,继承的注解不处理
Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);
// 返回解析到的注解
if (localOps != null) {
return localOps;
}
}
return ops;
}
} ;
// 确定类中以及方法中所有的缓存操作
return determineCacheOperations(provider) {
// 使用缓存注解解析器解析缓存注解
for (CacheAnnotationParser parser : this.annotationParsers) {
// 解析完成之后缓存注解信息被封装成CacheOperation
Collection<CacheOperation> annOps = provider.getCacheOperations(parser);
// 如果存在缓存注解信息
if (annOps != null) {
// 赋值给ops
if (ops == null) {
ops = annOps;
}
// 如果ops不为空,将又有的缓存注解信息与新解析的缓存注解信息合并
else {
Collection<CacheOperation> combined = new ArrayList<>(ops.size() + annOps.size());
combined.addAll(ops);
combined.addAll(annOps);
ops = combined;
}
}
}
// 返回解析过后的注解信息
return ops;
}
}
// 如果解析到了缓存注解信息,直接结束,因为可以确定需要aop
if (opDef != null) {
return opDef;
}
// 第二次解析,正在调用的目标类中的方法中不存在缓存注解,再解析该类上的注解
opDef = findCacheOperations(specificMethod.getDeclaringClass());
// 类中解析到了,表示也需要代理
if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
return opDef;
}
// specificMethod是被调用的类的方法对象,根据上面注释代码,method可能是原始方法,CBLIB方法,也可能是接口的方法对象
// 例如:targetClass = B B impl A => B.test() 此时,specificMethod = B.test() , method = A.test()
// specificMethod != method,表示该方法是继承或者实现过来的,不是自身的方法
if (specificMethod != method) {
// 再通过method本身来找方法上的注解
opDef = findCacheOperations(method);
if (opDef != null) {
return opDef;
}
// 最后在找method所属的类或者接口上的注解
opDef = findCacheOperations(method.getDeclaringClass());
if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
return opDef;
}
}
// 都没找到,表示不需要代理
return null;
}
if (cacheOps != null) {
// 解析到了缓存的注解信息,缓存
this.attributeCache.put(cacheKey, cacheOps);
} else {
// 没有解析到,标记该类没有解析到缓存注解
this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE);
}
return cacheOps;
}
}));
}
}
}
}
} else {
// 没有切入点的切面,默认都可用
return true;
}
}){
// 保存可用的切面
eligibleAdvisors.add(candidate);
}
}
}
// 给子类实现,扩展可用的切面
extendAdvisors(eligibleAdvisors);
// 如果存在可用的切面,进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
// 返回可用的切面
return eligibleAdvisors;
}
}
// 如果specificInterceptors为空,没找到可用的切面
// 否则需要创建代理
if (specificInterceptors != DO_NOT_PROXY) {
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
return proxy;
}
}
}
}
return bean;
}
}
// 目标方法执行拦截器
// 先看文Spring中JDK动态代理和CBLIB代理的拦截逻辑
// 因为创建的代理对象调用目标方法都会执行代理对象的拦截器逻辑
// 这个拦截逻辑就是获取符合条件的所有拦截的一个集合,然后一一执行
// 我们Asycn注解的话,只有一个拦截器,就是给定的CacheInterceptor
public class CacheInterceptor extends CacheAspectSupport implements SmartInitializingSingleton, MethodInterceptor {
// 所有的bean都初始化完毕的回调
public void afterSingletonsInstantiated() {
// 如果不存在缓存解析器
if (getCacheResolver() == null) {
// 通过默认缓存管理器延迟初始化缓存解析器
try {
// 从Spring容器中获取CacheManager缓存管理器,并且到拦截器中
setCacheManager(this.beanFactory.getBean(CacheManager.class)) {
// 实际上是设置缓存解析器,将缓存管理器封装到缓存解析器中,默认为SimpleCacheResolver
this.cacheResolver = SingletonSupplier.of(new SimpleCacheResolver(cacheManager));
}
}
// 没有缓存管理器,则抛出异常
catch (NoUniqueBeanDefinitionException ex) {
throw new IllegalStateException("No CacheResolver specified, and no unique bean of type " +
"CacheManager found. Mark one as primary or declare a specific CacheManager to use.");
}
}
// 标记当前类已经初始化完毕
this.initialized = true;
}
// 拦截器的拦截方法
public Object invoke(final MethodInvocation invocation) throws Throwable {
// 获取方法对象
Method method = invocation.getMethod();
// 将拦截器链逻辑封装成一个函数,在下面execute进行回调
CacheOperationInvoker aopAllianceInvoker = () -> {
// 执行下一个拦截器
return invocation.proceed();
};
// 执行目标方法
return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments()) {
// 是否初始化了,在afterSingletonsInstantiated方法中会初始化Cache解析器并且标识初始化成功
if (this.initialized) {
// 获取目标类
Class<?> targetClass = getTargetClass(target);
// 获取操作缓存注解的数据源对象
CacheOperationSource cacheOperationSource = getCacheOperationSource();
// 这个数据源肯定不为空,注册bean的时候注册了
if (cacheOperationSource != null) {
// 从缓存数据源中根据方法和目标类获取解析好的注解信息
// 因为在这之前,在是否需要创建代理对象的时候,就解析了该这些缓存注解
// Object cacheKey = getCacheKey(method, targetClass);进行缓存的
Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
// 如果存在缓存注解
if (!CollectionUtils.isEmpty(operations)) {
// 真正执行,详见下面execute方法
return execute(invoker, method, new CacheOperationContexts(operations, method, args, target, targetClass){
this.contexts = new LinkedMultiValueMap<>(operations.size());
// 将所有的缓存操作,按照类型分类,存入contexts中
for (CacheOperation op : operations) {
this.contexts.add(op.getClass(), getOperationContext(op, method, args, target, targetClass){
// 获取缓存的元数据
CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass){
// 元数据的缓存Key
CacheOperationCacheKey cacheKey = new CacheOperationCacheKey(operation, method, targetClass);
// 是否已经处理过
CacheOperationMetadata metadata = this.metadataCache.get(cacheKey);
// 没有处理过
if (metadata == null) {
// 获取Key的生成器
KeyGenerator operationKeyGenerator;
// 如果注解标记了生成器
if (StringUtils.hasText(operation.getKeyGenerator())) {
// 从spring中获取
operationKeyGenerator = getBean(operation.getKeyGenerator(), KeyGenerator.class);
}
else {
//
operationKeyGenerator = getKeyGenerator(){
// 使用默认的SimpleKeyGenerator
// private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);
return this.keyGenerator.obtain();
}
}
// 获取缓存解析器
CacheResolver operationCacheResolver;
// 如果注解中中配置了指定的缓存解析器
if (StringUtils.hasText(operation.getCacheResolver())) {
// 从Spring中获取
operationCacheResolver = getBean(operation.getCacheResolver(), CacheResolver.class);
}
// 如果没有注解设置缓存解析器,但是设置了缓存管理器
else if (StringUtils.hasText(operation.getCacheManager())) {
// 获取缓存管理器
CacheManager cacheManager = getBean(operation.getCacheManager(), CacheManager.class);
// 创建新的SimpleCacheResolver解析器
operationCacheResolver = new SimpleCacheResolver(cacheManager);
}
// 如果注解都没配置
else {
// 获取当前类的缓存解析器
// 也就是说有没有手动给当前CacheInterceptor类设置缓存管理器或者缓存解析器
// 如果设置了就有,如果没有设置,就抛异常
operationCacheResolver = getCacheResolver();
Assert.state(operationCacheResolver != null, "No CacheResolver/CacheManager set");
}
// 封装成元数据对象
metadata = new CacheOperationMetadata(operation, method, targetClass,operationKeyGenerator, operationCacheResolver);
// 缓存起来
this.metadataCache.put(cacheKey, metadata);
}
return metadata;
}
// 创建缓存操作的上下文
return new CacheOperationContext(metadata, args, target){
this.metadata = metadata;
this.args = extractArgs(metadata.method, args);
this.target = target;
// 自动根据命名空间解析缓存
this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver){
// 使用缓存解析器解析缓存
Collection<? extends Cache> caches = cacheResolver.resolveCaches(context){
// 获取缓存命名空间
Collection<String> cacheNames = getCacheNames(context){
// 获取注解中的命名空间
return context.getOperation().getCacheNames();
}
// 根据名称获取的所有缓存
Collection<Cache> result = new ArrayList<>(cacheNames.size());
// 遍历所有的命名空间
for (String cacheName : cacheNames) {
// 通过缓存管理器获取对应命名空间的缓存
// 这里根据不同的缓存管理器来操作,有不同的实现,我们只讲ConcurrentMapCacheManager
Cache cache = getCacheManager().getCache(cacheName){
// 缓map中获取之前加载过的缓存对象
Cache cache = this.cacheMap.get(name);
// 之前没有缓存过,并且是动态的(默认为true)
// 如果单独设置了cacheNames,dynamic会变为false
// public void setCacheNames(@Nullable Collection<String> cacheNames) {
// if (cacheNames != null) {
// for (String name : cacheNames) {
// this.cacheMap.put(name, createConcurrentMapCache(name));
// }
// this.dynamic = false;
// }
// else {
// this.dynamic = true;
// }
// }
if (cache == null && this.dynamic) {
// 双重校验
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
// 创建缓存
cache = createConcurrentMapCache(name){
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
// 创建缓存对象
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),isAllowNullValues(), actualSerialization);
}
// 保存起来
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
if (cache == null) {
throw new IllegalArgumentException("Cannot find cache named '" +cacheName + "' for " + context.getOperation());
}
// 保存缓存
result.add(cache);
}
return result;
}
return caches;
}
this.cacheNames = createCacheNames(this.caches){
Collection<String> names = new ArrayList<>();
// 获取缓存的名称
for (Cache cache : caches) {
names.add(cache.getName());
}
return names;
}
}
});
}
// 获取方法中@Cacheable注解上是否标记了sync的值,如果没有,就是false
// 它标记了多个线程是否可以同时查询这个缓存,如果不同步,多个线程可能会出现多次放入缓存操作
this.sync = determineSyncFlag(method){
// 获取@Cacheable类型的缓存
List<CacheOperationContext> cacheOperationContexts = this.contexts.get(CacheableOperation.class);
// 如果没有就不需要管
if (cacheOperationContexts == null) {
return false;
}
boolean syncEnabled = false;
// 遍历所有的@Cacheable方法
for (CacheOperationContext cacheOperationContext : cacheOperationContexts) {
// 获取注解中的值
if (((CacheableOperation) cacheOperationContext.getOperation()).isSync()) {
// 如果为true,表示开启了同步
syncEnabled = true;
break;
}
}
// 如果开启了同步,要校验
if (syncEnabled) {
// 这个方法只能有Cacheable注解,不能有其他的缓存注解
if (this.contexts.size() > 1) {
throw new IllegalStateException("@Cacheable(sync=true) cannot be combined with other cache operations on '" + method + "'");
}
// 并且只能有一个Cacheable注解
if (cacheOperationContexts.size() > 1) {
throw new IllegalStateException("Only one @Cacheable(sync=true) entry is allowed on '" + method + "'");
}
//
CacheOperationContext cacheOperationContext = cacheOperationContexts.iterator().next();
CacheableOperation operation = (CacheableOperation) cacheOperationContext.getOperation();
// 只能操作一个cacheNames命名空间中的缓存
if (cacheOperationContext.getCaches().size() > 1) {
throw new IllegalStateException("@Cacheable(sync=true) only allows a single cache on '" + operation + "'");
}
// 缓存开启同步的情况下,不能配置unless
// unless和condition有点类似,它是表示当前unless标注的条件不满足的情况下,才会更新缓存,它可以引用最终的结果作为el表达式
// 而condition决定是否需要执行该缓存,一个是开始决定,一个是结束决定
if (StringUtils.hasText(operation.getUnless())) {
throw new IllegalStateException("@Cacheable(sync=true) does not support unless attribute on '" + operation + "'");
}
return true;
}
return false;
}
});
}
}
}
// 如果没有初始化,说明缓存管理器没有设置,无法处理缓存,直接执行invocation.proceed();方法
return invoker.invoke();
}
}
// 执行缓存操作
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
// return execute(invoker, method, new CacheOperationContexts(operations, method, args, target, targetClass));
// 获取方法中@Cacheable注解上是否标记了sync的值,如果没有,就是false
// 它标记了多个线程是否可以同时查询这个缓存,多个线程可能会出现多次放入缓存操作
if (contexts.isSynchronized()) {
// 获取所有的@Cacheable的注解信息
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
// 如果condition条件符合,下面有解析
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
// 获取key,下面也有解析
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
// 获取@Cacheable注解的命名空间的所有缓存
Cache cache = context.getCaches().iterator().next();
// 执行目标方法
Object result = invokeOperation(invoker);
// 将目标方法拆包,可能需要从Optional中提取出来,也可能不需要
Callable<Object> valueLoader = () -> unwrapReturnValue(result);
// 再包装成Optional对象
return wrapCacheValue(method, cache.get(key, valueLoader));
} else {
// 直接执行目标方法
return invokeOperation(invoker);
}
}
// 第一步: 处理标了执行目标方法之前就要删除缓存的操作@CacheEvict
// 执行删除缓存操作,处理@CacheEvict标注了目标方法执行之前beforeInvocation删除缓存的操作
// 无论目标方法是否出现异常,缓存都删除成功
processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT) {
// 遍历所有的CacheEvict注解信息
for (CacheOperationContext context : contexts) {
// 获取注解的元信息
CacheEvictOperation operation = (CacheEvictOperation) context.metadata.operation;
// 传递的参数为true:,判断如果注解标注了beforeInvocation=true(默认值为false)
// true表示在方法执行之前删除缓存,否则在方法之后删除缓存
// 再需要判断在注解中设置了condition是否符合条件,只有符合条件才会删除
// @CacheEvict(value = "myCache", key = "#userId", condition = "#result != null")
if (beforeInvocation == operation.isBeforeInvocation()
&& isConditionPassing(context, result) {
// 是否被解析过表达式
if (this.conditionPassing == null) {
// 如果设置了条件
if (StringUtils.hasText(this.metadata.operation.getCondition())) {
// 创建一个计算上下文对象
EvaluationContext evaluationContext = createEvaluationContext(result) {
// 封装缓存相关的信息对象
CacheExpressionRootObject rootObject = new CacheExpressionRootObject(caches, method, args, target, targetClass);
// 创建缓存计算上下文
CacheEvaluationContext evaluationContext = new CacheEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer());
// 传递的result为NO_RESULT
if (result == RESULT_UNAVAILABLE) {
evaluationContext.addUnavailableVariable(RESULT_VARIABLE);
}
// 如何有结果,就会将返回结果保存到计算上下文中
else if (result != NO_RESULT) {
evaluationContext.setVariable(RESULT_VARIABLE, result);
}
// 如果为NO_RESULT,表示为初始化,给计算上下文中设置对应的Bean解析器,用于解析条件中可能存在的beanName
if (beanFactory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
return evaluationContext;
}
// 使用计算器计算条件是否符合
// 内部使用new SpelExpressionParser()解析spel表达式,然后在进行判断
this.conditionPassing = evaluator.condition(this.metadata.operation.getCondition(),this.metadata.methodKey, evaluationContext);
} else {
// 如果没有设定condition条件,就不需要校验
this.conditionPassing = true;
}
}
// 返回是否符合条件
return this.conditionPassing;
})
{
// 删除缓存
performCacheEvict(context, operation, result){
// 获取缓存Key
Object key = null;
// 遍历所有的缓存
for (Cache cache : context.getCaches()) {
// 注解是否配置了allEntries属性,默认为false
// 如果为true,表示清空缓存
if (operation.isCacheWide()) {
// 清空缓存
doClear(cache, operation.isBeforeInvocation()){
try {
// 是否立即清理,isBeforeInvocation传递的为true
if (immediate) {
// 删除缓存,执行缓存的失效逻辑,这个是不同的实现
// 现在我们讲基于内存的ConcurrentMapCache实现
cache.invalidate(){
// private final ConcurrentMap<Object, Object> store;
boolean notEmpty = !this.store.isEmpty();
this.store.clear();
return notEmpty;
}
}
else {
cache.clear();{
this.store.clear();
}
}
}
catch (RuntimeException ex) {
// 如果清理缓存发生异常,使用异常处理器处理
getErrorHandler().handleCacheClearError(ex, cache);
}
}
}
else {
// 如果没有设置allEntries属性,表示只删除当前key
if (key == null) {
// 生成一个key
key = generateKey(context, result){
return context.generateKey(result){
// 如果注解设置了key
if (StringUtils.hasText(this.metadata.operation.getKey())) {
// 内部使用new SpelExpressionParser()解析spel表达式,获取到真实的key
EvaluationContext evaluationContext = createEvaluationContext(result);
return evaluator.key(this.metadata.operation.getKey(), this.metadata.methodKey, evaluationContext);
}
// 如果没有设置key,使用给定的key生成器生成key
// keyGenerator:Spring存在使用Spring配置的keyGenerator,如果不存在使用默认的SimpleKeyGenerator
return this.metadata.keyGenerator.generate(this.target, this.metadata.method, this.args);
}
}
}
doEvict(cache, key, operation.isBeforeInvocation()){
try {
// 是否立即清理
// 现在我们讲基于内存的ConcurrentMapCache实现
if (immediate) {
cache.evictIfPresent(key){
return (this.store.remove(key) != null);
}
}
else {
cache.evict(key){
this.store.remove(key);
}
}
}
catch (RuntimeException ex) {
// 如果清理缓存发生异常,使用异常处理器处理
getErrorHandler().handleCacheEvictError(ex, cache, key);
}
}
}
}
}
}
}
}
// 第二步,检查@Cacheable注解,查询缓存是否命中
// 检查当前方法是否有@Cacheable匹配条件的缓存项
Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)){
// 默认的结果值
Object result = CacheOperationExpressionEvaluator.NO_RESULT;
// 遍历所有的Cacheable类型注解信息
for (CacheOperationContext context : contexts) {
// 判断注解的condition是否符合条件,上面有详细解释
if (isConditionPassing(context, result)) {
// 生成key,上面有详细解释
Object key = generateKey(context, result);
// 查找缓存值
Cache.ValueWrapper cached = findInCaches(context, key){
// 找到当前注解标注的命名空间中的所有缓存
for (Cache cache : context.getCaches()) {
// 获取缓存值
Cache.ValueWrapper wrapper = doGet(cache, key){
return cache.get(key);
}
if (wrapper != null) {
return wrapper;
}
}
return null;
}
// 找到了对应的缓存
if (cached != null) {
return cached;
}
}
}
return null;
}
// 如果没有命中缓存,表示缓存是新增的,新建一个put操作
// 如果没有找到缓存项,保存需要缓存的key的请求
List<CachePutRequest> cachePutRequests = new LinkedList<>();
// 如果没有找到缓存项,缓存命中
if (cacheHit == null) {
// 没有缓存命中,表示该方法需要被缓存,添加一个添加缓存的请求,后面统一添加
collectPutRequests(contexts.get(CacheableOperation.class),CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests){
// 遍历所有的@Cacheable注解信息
for (CacheOperationContext context : contexts) {
// condition条件通过
if (isConditionPassing(context, result)) {
// 生成Key
Object key = generateKey(context, result);
// 保存一个增加缓存的请求对象
putRequests.add(new CachePutRequest(context, key));
}
}
}
}
Object cacheValue;
Object returnValue;
// 如果找到了缓存信息,表示缓存命中
if (cacheHit != null
// 判断是否存在有要保存的缓存
&& !hasCachePut(contexts){
// 获取CachePut注解信息
Collection<CacheOperationContext> cachePutContexts = contexts.get(CachePutOperation.class);
// 需要排除的缓存
Collection<CacheOperationContext> excluded = new ArrayList<>();
// 遍历所有的CachePut注解信息
for (CacheOperationContext context : cachePutContexts) {
// 如果不匹配condition
if (!context.isConditionPassing(CacheOperationExpressionEvaluator.RESULT_UNAVAILABLE)) {
// 当前注解信息排除
excluded.add(context);
}
}
// 检查是否所有的CachePut注解都被排除了
return (cachePutContexts.size() != excluded.size());
})
{
// 如果没有put请求,则只使用缓存命中操作,因为可能这个方法同时存在缓存新增和缓存修改注解
// 直接获取缓存的值
cacheValue = cacheHit.get();
// 包装缓存值
returnValue = wrapCacheValue(method, cacheValue){
// 统一将值封装为Optional对象
if (method.getReturnType() == Optional.class && (cacheValue == null || cacheValue.getClass() != Optional.class)) {
return Optional.ofNullable(cacheValue);
}
return cacheValue;
}
} else {
// 如果没有找到缓存,表示缓存没有命中
returnValue = invokeOperation(invoker){
// 执行目标方法
return invoker.invoke();
}
// 将值进行拆包,就是将Optional中的值拆出来
cacheValue = unwrapReturnValue(returnValue){
return ObjectUtils.unwrapOptional(returnValue);
}
}
// 第三步: 处理所有的put操作,并缓存起来
// 继续收集所有添加的缓存,上面有这个代码解释
collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
// 遍历所有的put添加缓存请求
// 处理任何收集到的新增请求,无论是来自@CachePut还是@Cacheable miss
for (CachePutRequest cachePutRequest : cachePutRequests) {
// 执行请求
cachePutRequest.apply(cacheValue){
// 判断是否可以put
if (this.context.canPutToCache(result){
// 解析注解中的unless条件
String unless = "";
// 根据不同类型,解析不同注解中的unless值
if (this.metadata.operation instanceof CacheableOperation) {
unless = ((CacheableOperation) this.metadata.operation).getUnless();
}
else if (this.metadata.operation instanceof CachePutOperation) {
unless = ((CachePutOperation) this.metadata.operation).getUnless();
}
// 解析unless的el表达式
if (StringUtils.hasText(unless)) {
EvaluationContext evaluationContext = createEvaluationContext(value);
// 解析unless条件,前面加一个"!",表示值与unless的值对立才添加缓存
return !evaluator.unless(unless, this.metadata.methodKey, evaluationContext);
}
// 没有unless条件
return true;
})
{
// 遍历所有的缓存
for (Cache cache : this.context.getCaches()) {
// 将当前key和结果保存到缓存中
doPut(cache, this.key, result){
cache.put(key, result);{
// 调用的是ConcurrentMapCache的实现
this.store.put(key, toStoreValue(value));
}
}
}
}
}
}
// 第四步: 和第一步一样,执行删除的时机一个再执行目标方法删除,一个在执行目标方法之后执行
// 执行删除缓存操作,处理@CacheEvict的默认情况,上面有完全一样的代码解释
// 上面执行的是在目标方法之前删除,现在是目标方法之后删除,执行时机不一样,其他的完全一样
processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
// 返回目标方法执行的结果
return returnValue;
}
}
Spring中@EnableCache的原理
于 2024-03-13 12:47:16 首次发布