转载请标明出处:
https://blog.csdn.net/bingospunky/article/details/79700773
本文出自马彬彬的博客

spring.cache.type: redis如何生效的?

在使用spring cache时,spring已经默认支持了几种缓存实现方式,我们可以通过在spring-boot配置文件中添加spring.cache.type: redis来设置使用redis方式实现cache。那么这句配置是如何剩下的呢?

在spring-boot-autoconfigure的jar文件中,org.springframework.boot.autoconfigure.cache包下有一系列XXXCacheConfiguration,在这些XXXCacheConfiguration中,有很多@ConditionalXXX注解,这样会进行一定的过滤,但仅靠@ConditionalXXX注解是不够的,因为@ConditionalXXX注解生效后,还不能辨别出唯一的一个XXXCacheConfiguration
每个XXXCacheConfiguration还有这样一个注解@Conditional({CacheCondition.class})。

@Conditional的声明是这样的:

Code1
org.springframework.context.annotation.Conditional

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

Condition的声明式这样的:

Code2
org.springframework.context.annotation

public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

Code3
org.springframework.boot.autoconfigure.cache.CacheCondition

class CacheCondition extends SpringBootCondition {
    CacheCondition() {
    }
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String sourceClass = "";
        if (metadata instanceof ClassMetadata) {
            sourceClass = ((ClassMetadata)metadata).getClassName();
        }
        Builder message = ConditionMessage.forCondition("Cache", new Object[]{sourceClass});
        RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(context.getEnvironment(), "spring.cache.");
        if (!resolver.containsProperty("type")) {
            return ConditionOutcome.match(message.because("automatic cache type"));
        } else {
            CacheType cacheType = CacheConfigurations.getType(((AnnotationMetadata)metadata).getClassName());
            String value = resolver.getProperty("type").replace('-', '_').toUpperCase();
            return value.equals(cacheType.name()) ? ConditionOutcome.match(message.because(value + " cache type")) : ConditionOutcome.noMatch(message.because(value + " cache type"));
        }
    }
}

CacheCondition继承SpringBootCondition。SpringBootCondition的代码如下:

Code4
org.springframework.boot.autoconfigure.condition.SpringBootCondition

public abstract class SpringBootCondition implements Condition {
    private final Log logger = LogFactory.getLog(this.getClass());
    public SpringBootCondition() {
    }
    public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String classOrMethodName = getClassOrMethodName(metadata);
        try {
            ConditionOutcome outcome = this.getMatchOutcome(context, metadata);
            this.logOutcome(classOrMethodName, outcome);
            this.recordEvaluation(context, classOrMethodName, outcome);
            return outcome.isMatch();
        } catch (NoClassDefFoundError var5) {
            throw new IllegalStateException("Could not evaluate condition on " + classOrMethodName + " due to " + var5.getMessage() + " not found. Make sure your own configuration does not rely on that class. This can also happen if you are @ComponentScanning a springframework package (e.g. if you put a @ComponentScan in the default package by mistake)", var5);
        } catch (RuntimeException var6) {
            throw new IllegalStateException("Error processing condition on " + this.getName(metadata), var6);
        }
    }
}

被@Conditional({CacheCondition.class})标记的XXXCacheConfiguration,会根据CacheCondition的matches方法的返回值来判断该XXXCacheConfiguration是否生效。

当spring加载的时候,Code4第4行的方法会被不断的回调,其中第二个参数是标记@Conditional({CacheCondition.class})这个注解的类的Class。比如这次回调传进来的metadata是RedisCacheConfiguration的Class生成的。在Code3的getMatchOutcome方法中,第7行的sourceClass的值是“RedisCacheConfiguration”,第14行,会根据RedisCacheConfiguration获取到的枚举类型是:CacheType.REDIS,第15行获取的value的值就是我们在配置文件中设置的spring.cache.type: redis的大写形式REDIS。这样matches方法会返回true,该XXXCacheConfiguration生效。

XXXCacheConfiguration为JCacheCacheConfiguration时,字符串不匹配,该JCacheCacheConfiguration不生效。

GitHub 加速计划 / sp / spring-boot
73.97 K
40.4 K
下载
spring-projects/spring-boot: 是一个用于简化Spring应用开发的框架。适合用于需要快速开发企业级Java应用的项目。特点是可以提供自动配置、独立运行和内置的Tomcat服务器,简化Spring应用的构建和部署。
最近提交(Master分支:1 个月前 )
fdf24c6c Closes gh-42976 4 天前
3c42ba8c * pr/42974: Fix copyright year of updated file Polish Closes gh-42974 4 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐