spring-boot-auto-configure:spring.cache.type如何生效
转载请标明出处:
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不生效。
更多推荐
所有评论(0)