自学做网站可以嘛上海网站建设开发电话
news/
2025/10/7 6:04:47/
文章来源:
自学做网站可以嘛,上海网站建设开发电话,萍乡网站建设哪家好哦,网站防盗链怎么做JetCache自动化配置加载
JetCache的配置加载主要是在jetcache-autoconfigure模块中完成的#xff0c;其中加载配置的核心类是JetCacheAutoConfiguration#xff0c;主要是用于创建全局性的一些Bean#xff0c;例如全局缓存配置类GlobalCacheConfig#xff0c;AutoConfigur…JetCache自动化配置加载
JetCache的配置加载主要是在jetcache-autoconfigure模块中完成的其中加载配置的核心类是JetCacheAutoConfiguration主要是用于创建全局性的一些Bean例如全局缓存配置类GlobalCacheConfigAutoConfigureBeans和SpringConfigProvider等源码如下
Configuration
ConditionalOnClass(GlobalCacheConfig.class)
ConditionalOnMissingBean(GlobalCacheConfig.class)
EnableConfigurationProperties(JetCacheProperties.class)
Import({RedisAutoConfiguration.class,CaffeineAutoConfiguration.class,MockRemoteCacheAutoConfiguration.class,LinkedHashMapAutoConfiguration.class,RedisLettuceAutoConfiguration.class,RedisSpringDataAutoConfiguration.class,RedissonAutoConfiguration.class})
public class JetCacheAutoConfiguration {public static final String GLOBAL_CACHE_CONFIG_NAME globalCacheConfig;Bean(destroyMethod shutdown)ConditionalOnMissingBeanpublic SpringConfigProvider springConfigProvider(Autowired ApplicationContext applicationContext,Autowired GlobalCacheConfig globalCacheConfig,Autowired(required false) EncoderParser encoderParser,Autowired(required false) KeyConvertorParser keyConvertorParser,Autowired(required false) ConsumerStatInfo metricsCallback) {return new JetCacheBaseBeans().springConfigProvider(applicationContext, globalCacheConfig,encoderParser, keyConvertorParser, metricsCallback);}Bean(name jcCacheManager,destroyMethod close)ConditionalOnMissingBeanpublic SimpleCacheManager cacheManager(Autowired SpringConfigProvider springConfigProvider) {SimpleCacheManager cacheManager new SimpleCacheManager();cacheManager.setCacheBuilderTemplate(springConfigProvider.getCacheBuilderTemplate());return cacheManager;}BeanConditionalOnMissingBeanpublic AutoConfigureBeans autoConfigureBeans() {return new AutoConfigureBeans();}Beanpublic static BeanDependencyManager beanDependencyManager() {return new BeanDependencyManager();}Bean(name GLOBAL_CACHE_CONFIG_NAME)public GlobalCacheConfig globalCacheConfig(AutoConfigureBeans autoConfigureBeans, JetCacheProperties props) {GlobalCacheConfig _globalCacheConfig new GlobalCacheConfig();_globalCacheConfig new GlobalCacheConfig();_globalCacheConfig.setHiddenPackages(props.getHiddenPackages());_globalCacheConfig.setStatIntervalMinutes(props.getStatIntervalMinutes());_globalCacheConfig.setAreaInCacheName(props.isAreaInCacheName());_globalCacheConfig.setPenetrationProtect(props.isPenetrationProtect());_globalCacheConfig.setEnableMethodCache(props.isEnableMethodCache());_globalCacheConfig.setLocalCacheBuilders(autoConfigureBeans.getLocalCacheBuilders());_globalCacheConfig.setRemoteCacheBuilders(autoConfigureBeans.getRemoteCacheBuilders());return _globalCacheConfig;}
}
无论是使用内存缓存LinkedHashMap和caffeine亦或是通过lettuce、redisson和spring-data-redis来操作Redis服务缓存数据其自动加载配置的操作基本上都是相似的。
例如LinkedHashMapAutoConfiguration完成LinkedHashMap类型的缓存初始化操作源码如下
/*** LinkedHashMap自动配置类*/
Component
Conditional(LinkedHashMapAutoConfiguration.LinkedHashMapCondition.class)
public class LinkedHashMapAutoConfiguration extends EmbeddedCacheAutoInit {public LinkedHashMapAutoConfiguration() {super(linkedhashmap);}Override/*** 初始化缓存* param ct 配置树* param cacheAreaWithPrefix 缓存区域名称包括前缀* return 初始化后的缓存*/protected CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix) {LinkedHashMapCacheBuilder builder LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder();parseGeneralConfig(builder, ct);return builder;}/*** LinkedHashMap条件类*/public static class LinkedHashMapCondition extends JetCacheCondition {public LinkedHashMapCondition() {super(linkedhashmap);}}
}其中LinkedHashMapCondition是一个自定义的条件类如果spring boot项目的application.yml文件中jetcache.local.${areaName} .type或jetcache.remote.${areaName}.type为linkedhashmap时就会构建LinkedHashMapAutoConfiguration对应的beanJetCacheCondition类的源码如下
public abstract class JetCacheCondition extends SpringBootCondition {/*** 缓存类型数组*/private String[] cacheTypes;/*** 构造方法* param cacheTypes 缓存类型数组*/protected JetCacheCondition(String... cacheTypes) {Objects.requireNonNull(cacheTypes, cacheTypes cant be null);Assert.isTrue(cacheTypes.length 0, cacheTypes length is 0);this.cacheTypes cacheTypes;}/*** 判断条件是否匹配* param conditionContext 条件上下文* param annotatedTypeMetadata 注解类型元数据* return 匹配结果*/Overridepublic ConditionOutcome getMatchOutcome(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {ConfigTree ct new ConfigTree((ConfigurableEnvironment) conditionContext.getEnvironment(), jetcache.);if (match(ct, local.) || match(ct, remote.)) {return ConditionOutcome.match();} else {return ConditionOutcome.noMatch(no match for cacheTypes[0]);}}/*** 判断是否匹配指定前缀* param ct 配置树* param prefix 前缀* return 是否匹配*/private boolean match(ConfigTree ct, String prefix) {MapString, Object m ct.subTree(prefix).getProperties();SetString cacheAreaNames m.keySet().stream().map((s) - s.substring(0, s.indexOf(.))).collect(Collectors.toSet());final ListString cacheTypesList Arrays.asList(cacheTypes);return cacheAreaNames.stream().anyMatch((s) - cacheTypesList.contains(m.get(s .type)));}
}同理如果想要使用redisson或lettuce中间件来进行远程缓存的处理则对应的自动化配置类的源码如下
Configuration
Conditional(RedissonAutoConfiguration.RedissonCondition.class)
public class RedissonAutoConfiguration {private static final String CACHE_TYPE redisson;public static class RedissonCondition extends JetCacheCondition {public RedissonCondition() {super(CACHE_TYPE);}}Beanpublic RedissonAutoInit redissonAutoInit() {return new RedissonAutoInit();}
}
在上面的RedissonAutoConfiguration.RedissonCondition条件类中对应的cacheTypes为redisson即当spring boot项目的application.yml文件中jetcache.local.${areaName} .type或jetcache.remote.${areaName}.type为redisson时就会构建RedissonAutoConfiguration对应的bean。
同理加载lettuce对应的自动化加载的源码如下
Configuration
Conditional(RedisLettuceAutoConfiguration.RedisLettuceCondition.class)
public class RedisLettuceAutoConfiguration {public static final String AUTO_INIT_BEAN_NAME redisLettuceAutoInit;public static class RedisLettuceCondition extends JetCacheCondition {public RedisLettuceCondition() {super(redis.lettuce);}}Bean(name {AUTO_INIT_BEAN_NAME})public RedisLettuceAutoInit redisLettuceAutoInit() {return new RedisLettuceAutoInit();}
}
JetCache自动初始化
上面介绍的都是各种缓存方式的自动化配置的类可以发现当自动化配置的Bean被创建后都会创建AbstractCacheAutoInit对应的Bean。JetCache的自动化的类图如下 上面所有类型的缓存初始化类最终都继承了InitializingBeanInitializingBean是Spring框架中的一个接口它定义了一个方法 afterPropertiesSet()。当一个bean实例化后Spring容器会自动调用该方法来完成一些初始化操作。
抽象类AbstractCacheAutoInit在实现InitializingBean接口时重写了afterPropertiesSet() 方法来实现一些特定的初始化逻辑。在 Spring 容器完成AbstractCacheAutoInit类型的bean的属性注入后会调用AbstractCacheAutoInit类的afterPropertiesSet() 方法来执行这些初始化逻辑。
我们先看一下AbstractCacheAutoInit类的afterPropertiesSet()方法源码如下
/*** 在属性设置之后调用的方法*/
Override
public void afterPropertiesSet() {// 如果还未初始化if (!inited) {// 上锁reentrantLock.lock();try{// 如果还未初始化if (!inited) {// 处理本地缓存构建器process(jetcache.local., autoConfigureBeans.getLocalCacheBuilders(), true);// 处理远程缓存构建器process(jetcache.remote., autoConfigureBeans.getRemoteCacheBuilders(), false);// 设置已初始化标志为trueinited true;}}finally {// 解锁reentrantLock.unlock();}}
}
上面的代码相对比较简单首先会判断是否已经进行初始化了如果没有就先用锁然后处理本地和远程缓存的处理器。实例autoConfigureBeans中的方法getLocalCacheBuilders()和getRemoteCacheBuilders()是用于获取本地和远程的缓存构建者类AutoConfigureBeans的源码很简单我们简单的看一下即可不做详细介绍。AutoConfigureBeans源码如下
public class AutoConfigureBeans {private MapString, CacheBuilder localCacheBuilders new HashMap();private MapString, CacheBuilder remoteCacheBuilders new HashMap();private MapString, Object customContainer Collections.synchronizedMap(new HashMap());public MapString, CacheBuilder getLocalCacheBuilders() {return localCacheBuilders;}public void setLocalCacheBuilders(MapString, CacheBuilder localCacheBuilders) {this.localCacheBuilders localCacheBuilders;}public MapString, CacheBuilder getRemoteCacheBuilders() {return remoteCacheBuilders;}public void setRemoteCacheBuilders(MapString, CacheBuilder remoteCacheBuilders) {this.remoteCacheBuilders remoteCacheBuilders;}public MapString, Object getCustomContainer() {return customContainer;}public void setCustomContainer(MapString, Object customContainer) {this.customContainer customContainer;}
}
其中AutoConfigureBeans类的Bean是在JetCacheAutoConfiguration类中被创建的。我们继续看AbstractCacheAutoInit类中process方法的逻辑其源码如下 /*** 处理缓存区域** param prefix 缓存前缀* param cacheBuilders 缓存构建器的映射* param local 是否为本地缓存*/private void process(String prefix, Map cacheBuilders, boolean local) {// 创建配置树解析器ConfigTree resolver new ConfigTree(environment, prefix);// 获取缓存区域的属性集合MapString, Object m resolver.getProperties();// 获取缓存区域的名称集合SetString cacheAreaNames resolver.directChildrenKeys();// 遍历缓存区域名称集合for (String cacheArea : cacheAreaNames) {// 获取缓存区域类型final Object configType m.get(cacheArea .type);// 判断缓存区域类型是否匹配指定的类型名称boolean match Arrays.stream(typeNames).anyMatch((tn) - tn.equals(configType));// 如果匹配失败则继续下个循环if (!match) {continue;}// 获取缓存区域的子树ConfigTree ct resolver.subTree(cacheArea .);// 初始化缓存区域的缓存logger.info(init cache area {} , type {}, cacheArea, typeNames[0]);CacheBuilder c initCache(ct, local ? local. cacheArea : remote. cacheArea);// 将缓存构建器添加到映射中cacheBuilders.put(cacheArea, c);}}这个函数用于处理缓存区域。首先根据给定的前缀和环境创建一个配置树解析器并获取缓存区域的属性和名称集合。然后遍历缓存区域名称集合获取每个区域的类型并与给定的类型名称进行比较。如果类型匹配则初始化该缓存区域的缓存并将缓存构建器添加到给定的映射中。
上面的方法会针对每一个areaName分别去调用initCache方法进行初始化操作接下来我们先看一下initCache方法的源码
protected abstract CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix);
AbstractCacheAutoInit类的initCache方法是一个抽象方法这就需要在子类中实现该方法我们接下来就开始分析主要的几个内存和Redis缓存的自动初始化类的源码了。
内存缓存自动初始化
LinkedHashMapAutoConfiguration类是基于LinkedHashMap来创建的内存缓存自动配置类该类继承自EmbeddedCacheAutoInit抽象类该类重写了initCache方法用于内存缓存的初始化操作该方法会创建用于创建LinkedHashMap类型的内存缓存的创建者并调用parseGeneralConfig方法解析JetCache内存缓存的配置。
为了便于理解我们先看一下JetCache中关于内存缓存的配置信息
jetcache:statIntervalMinutes: 15areaInCacheName: falsehidePackages: com.alibabalocal:default:type: caffeinelimit: 100keyConvertor: fastjson2 #其他可选fastjson/jacksonexpireAfterWriteInMillis: 100000otherArea:type: linkedhashmaplimit: 100keyConvertor: noneexpireAfterWriteInMillis: 100000
配置通用说明如下
属性默认值说明jetcache.statIntervalMinutes0统计间隔0表示不统计jetcache.areaInCacheNametrue(2.6-) false(2.7)jetcache-anno把cacheName作为远程缓存key前缀2.4.3以前的版本总是把areaName加在cacheName中因此areaName也出现在key前缀中。2.4.4以后可以配置为了保持远程key兼容默认值为true但是新项目的话false更合理些2.7默认值已改为false。jetcache.hiddenPackages无Cached和CreateCache自动生成name的时候为了不让name太长hiddenPackages指定的包名前缀被截掉jetcache.local.${area}.type无缓存类型。tair、redis为当前支持的远程缓存linkedhashmap、caffeine为当前支持的本地缓存类型jetcache.local.${area}.keyConvertorfastjson2key转换器的全局配置2.6.5已经支持的keyConvertorfastjson2/jackson 2.6.5-只有一个已经实现的keyConvertorfastjson。仅当使用CreateCache且缓存类型为LOCAL时可以指定为none此时通过equals方法来识别key。方法缓存必须指定keyConvertorjetcache.local.${area}.limit100每个缓存实例的最大元素的全局配置仅local类型的缓存需要指定。注意是每个缓存实例的限制而不是全部比如这里指定100然后用CreateCache创建了两个缓存实例并且注解上没有设置localLimit属性那么每个缓存实例的限制都是100jetcache.local.${area}.expireAfterWriteInMillis无穷大以毫秒为单位指定超时时间的全局配置(以前为defaultExpireInMillis)jetcache.local.${area}.expireAfterAccessInMillis0需要jetcache2.2以上以毫秒为单位指定多长时间没有访问就让缓存失效当前只有本地缓存支持。0表示不使用这个功能。
内存缓存中的常用的配置主要是type、keyConvertor、limit、expireAfterWriteInMillis和expireAfterAccessInMillis。由于系统所在的服务器对每个服务的占用内存比较敏感所以需要对内存缓存中的数据量进行限制这就需要配置limit如果不配置则每个缓存实例就默认是100个一旦某个缓存实例的缓存达到limit的限制后新的缓存数据就无法保存到内存缓存中了所以合理配置limit的值很重要鉴于可以在查询函数中通过配置Cached注解中的localLimit来设置每个缓存实例的limit且Cached注解中的localLimit优先于全局配置中的limit。keyConvertor可以使用默认的配置即linkedhashmap类型的缓存使用nonecaffeine类型的缓存使用fastjson2。Cached注解中的keyConvertor来设置每个缓存实例的keyConvertor且Cached注解中的keyConvertor优先于全局配置中的keyConvertor。
initCache方法的源码如下 /*** 重写方法用于初始化缓存* param ct 缓存的配置树* param cacheAreaWithPrefix 缓存区服包括前缀* return 返回构建好的缓存*/Overrideprotected CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix) {LinkedHashMapCacheBuilder builder LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder();parseGeneralConfig(builder, ct);return builder;}创建LinkerHashMap类型的缓存构建者的源码如下
public class LinkedHashMapCacheBuilderT extends EmbeddedCacheBuilderT extends EmbeddedCacheBuilderT {/*** LinkedHashMapCacheBuilder的内部类*/public static class LinkedHashMapCacheBuilderImpl extends LinkedHashMapCacheBuilderLinkedHashMapCacheBuilderImpl {}/*** 创建一个LinkedHashMapCacheBuilderImpl实例* * return 返回LinkedHashMapCacheBuilderImpl实例*/public static LinkedHashMapCacheBuilderImpl createLinkedHashMapCacheBuilder() {return new LinkedHashMapCacheBuilderImpl();}/*** 私有构造方法*/protected LinkedHashMapCacheBuilder() {buildFunc((c) - new LinkedHashMapCache((EmbeddedCacheConfig) c));}
}在上面构建的LinkedHashMapCacheBuilder实例时LinkedHashMapCacheBuilder的构造函数会初始化相应的缓存类LinkedHashMapCache。这里紧急简单介绍一下后面会详细就缓存构建者进行描述。
CaffeineAutoConfiguration类是基于Caffeine来创建的内存缓存自动配置类该类继承自EmbeddedCacheAutoInit抽象类该类重写了initCache方法该方法会创建用于创建Caffeine类型的内存缓存的创建者并调用parseGeneralConfig方法解析JetCache的配置。源码如下
Overrideprotected CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix) {CaffeineCacheBuilder builder CaffeineCacheBuilder.createCaffeineCacheBuilder();parseGeneralConfig(builder, ct);return builder;}
同样关于构建CaffeineCacheBuilder相应的代码逻辑也放在后面再进行介绍。
内存缓存LinkedHashMap和caffeine的自动初始化类都是继承自EmbeddedCacheAutoInit抽象类主要是解析配置的内存缓存的最大缓存数量。EmbeddedCacheAutoInit类的源码如下
public abstract class EmbeddedCacheAutoInit extends AbstractCacheAutoInit {public EmbeddedCacheAutoInit(String... cacheTypes) {super(cacheTypes);}Overrideprotected void parseGeneralConfig(CacheBuilder builder, ConfigTree ct) {super.parseGeneralConfig(builder, ct);EmbeddedCacheBuilder ecb (EmbeddedCacheBuilder) builder;ecb.limit(Integer.parseInt(ct.getProperty(limit, String.valueOf(CacheConsts.DEFAULT_LOCAL_LIMIT))));}
}
解析配置文件的逻辑放到下面的JetCache配置解析章节进行讲述这里不做过多描述。
EmbeddedCacheAutoInit
我们上面提到内存缓存的自动化配置类的父类都是EmbeddedCacheAutoInit所以这里我们需要先来看一下类EmbeddedCacheAutoInit的源码。
public abstract class EmbeddedCacheAutoInit extends AbstractCacheAutoInit {public EmbeddedCacheAutoInit(String... cacheTypes) {super(cacheTypes);}Overrideprotected void parseGeneralConfig(CacheBuilder builder, ConfigTree ct) {super.parseGeneralConfig(builder, ct);EmbeddedCacheBuilder ecb (EmbeddedCacheBuilder) builder;ecb.limit(Integer.parseInt(ct.getProperty(limit, String.valueOf(CacheConsts.DEFAULT_LOCAL_LIMIT))));}
}
上面的parseGeneralConfig方法会先调用父类的parseGeneralConfig方法解析常用配置然后将配置中的limit同步到EmbeddedCacheBuilder实例的limit属性中。
接下来我们再来看一下EmbeddedCacheAutoInit的父类AbstractCacheAutoInit的parseGeneralConfig方法的源码如下 // 解析通用配置protected void parseGeneralConfig(CacheBuilder builder, ConfigTree ct) {// 获得缓存构建器AbstractCacheBuilder acb (AbstractCacheBuilder) builder;// 设置key转换器acb.keyConvertor(new ParserFunction(ct.getProperty(keyConvertor, KeyConvertor.FASTJSON2)));// 获取expireAfterWriteInMillis配置String expireAfterWriteInMillis ct.getProperty(expireAfterWriteInMillis);// 保持与2.1版本的兼容性如果未找到expireAfterWriteInMillis尝试获取defaultExpireInMillis配置if (expireAfterWriteInMillis null) {expireAfterWriteInMillis ct.getProperty(defaultExpireInMillis);}// 如果expireAfterWriteInMillis配置存在则将其转换为long型并设置到acb对象中if (expireAfterWriteInMillis ! null) {acb.setExpireAfterWriteInMillis(Long.parseLong(expireAfterWriteInMillis));}// 获取expireAfterAccessInMillis配置String expireAfterAccessInMillis ct.getProperty(expireAfterAccessInMillis);// 如果expireAfterAccessInMillis配置存在则将其转换为long型并设置到acb对象中if (expireAfterAccessInMillis ! null) {acb.setExpireAfterAccessInMillis(Long.parseLong(expireAfterAccessInMillis));}}这个函数用于解析通用配置信息。首先将传入的builder对象转换为AbstractCacheBuilder类型并设置keyConvertor为通过ct对象获取的属性值或默认值。然后从ct对象获取expireAfterWriteInMillis属性值如果该属性值为空则使用defaultExpireInMillis属性值。最后将获取到的expireAfterWriteInMillis和expireAfterAccessInMillis属性值转换为long类型并设置到acb对象中。
Redis缓存自动初始化
在RedissonAutoConfiguration类中redissonAutoInit()函数会创建RedissonAutoInit对应的bean在RedisLettuceAutoConfiguration类中redisLettuceAutoInit()函数会创建RedisLettuceAutoInit对应的bean。同理RedisSpringDataAutoConfiguration类中springDataRedisAutoInit()函数会创建SpringDataRedisAutoInit对应的bean。根据上面的JetCache的自动化的类图可以发现RedissonAutoInit、RedisLettuceAutoInit和SpringDataRedisAutoInit都是ExternalCacheAutoInit的子类所以主要是初始化函数initCache方法的实现会有所不同我们在下面会着重的就RedissonAutoInit、RedisLettuceAutoInit和SpringDataRedisAutoInit的initCache方法进行详细的介绍一下。
鉴于下面的初始化方法中会获取JetCache的配置创建Redis连接所以我们优先看一下JetCache中关于远程缓存的配置说明会便于下面的源码的理解。
jetcache:statIntervalMinutes: 15areaInCacheName: falsehidePackages: com.alibabaremote:default:type: redis.lettucekeyConvertor: fastjson2broadcastChannel: projectAmode: cluster #redis模式cluster集群模式#readFrom: slavePreferreduri:- redis://127.0.0.1:7000 #redis服务的//IP:Port- redis://127.0.0.1:7001- redis://127.0.0.1:7002otherArea:type: redis.lettucekeyConvertor: fastjson2 #其他可选fastjson/jacksonbroadcastChannel: projectAvalueEncoder: java #其他可选kryo/kryo5valueDecoder: java #其他可选kryo/kryo5poolConfig:minIdle: 5maxIdle: 20maxTotal: 50host: ${redis.host}port: ${redis.port}
配置通用说明如下
属性默认值说明jetcache.remote.${area}.type无缓存类型。tair、redis为当前支持的远程缓存linkedhashmap、caffeine为当前支持的本地缓存类型jetcache.remote.${area}.keyConvertorfastjson2key转换器的全局配置2.6.5已经支持的keyConvertorfastjson2/jackson 2.6.5-只有一个已经实现的keyConvertorfastjson。仅当使用CreateCache且缓存类型为LOCAL时可以指定为none此时通过equals方法来识别key。方法缓存必须指定keyConvertorjetcache.remote.${area}.valueEncoderjava序列化器的全局配置。仅remote类型的缓存需要指定2.7可选java/kryo/kryo52.6-可选java/kryojetcache.remote.${area}.valueDecoderjava序列化器的全局配置。仅remote类型的缓存需要指定2.7可选java/kryo/kryo52.6-可选java/kryojetcache.remote.${area}.expireAfterWriteInMillis无穷大以毫秒为单位指定超时时间的全局配置(以前为defaultExpireInMillis)jetcache.remote.${area}.broadcastChannel无 jetcahe2.7的两级缓存支持更新以后失效其他JVM中的local cache但多个服务共用redis同一个channel可能会造成广播风暴需要在这里指定channel你可以决定多个不同的服务是否共用同一个channel。如果没有指定则不开启。 jetcache.remote.${area}.mode无缓存模式cluster集群模式jetcache.remote.${area}.uri无缓存服务的URI可以支持多个jetcache.remote.${area}.ip无缓存服务的IP地址jetcache.remote.${area}.port无缓存服务的端口
上表中${area}对应Cached和CreateCache的area属性。注意如果注解上没有指定area默认值是default。
RedissonAutoInit
RedissonAutoInit继承自抽象类ExternalCacheAutoInit在initCache方法中主要是获取所有RedissonClient的bean映射如果找到了多个RedissonClient的bean则根据配置决定使用哪个RedissonClient。解析spring boot项目的application.yml文件中jetcache.remote .${areaName}中的Redis配置创建用于创建Redisson类型的内存缓存的创建者RedissonCacheBuilder并调用parseGeneralConfig方法解析JetCache的配置。源码如下
/*** 初始化缓存** param ct 缓存配置树* param cacheAreaWithPrefix 缓存区域名称包括前缀* return 缓存构建器*/
Override
protected CacheBuilder initCache(final ConfigTree ct, final String cacheAreaWithPrefix) {// 获取RedissonClient的beanfinal MapString, RedissonClient beans this.context.getBeansOfType(RedissonClient.class);if (beans.isEmpty()) {throw new CacheConfigException(no RedissonClient in spring context);}RedissonClient client beans.values().iterator().next();if (beans.size() 1) {// 获取配置树中的redissonClient属性值final String redissonClientName ct.getProperty(redissonClient);if (Objects.isNull(redissonClientName) || redissonClientName.isEmpty()) {throw new CacheConfigException(redissonClient is required, because there is multiple RedissonClient in Spring context);}if (!beans.containsKey(redissonClientName)) {throw new CacheConfigException(there is no RedissonClient named redissonClientName in Spring context);}client beans.get(redissonClientName);}// 创建外部缓存构建器并设置RedissonClientfinal ExternalCacheBuilder? builder RedissonCacheBuilder.createBuilder().redissonClient(client);// 解析通用配置并添加到构建器中parseGeneralConfig(builder, ct);return builder;
}函数的功能是初始化缓存具体实现如下 获取所有RedissonClient的bean映射如果找到了多个RedissonClient的bean则根据配置决定使用哪个RedissonClient。创建一个ExternalCacheBuilder对象并将RedissonClient设置为其属性。解析通用配置并添加到CacheBuilder中。 RedisLettuceAutoInit
RedisLettuceAutoInit继承自抽象类ExternalCacheAutoInit在initCache方法相较于RedissonAutoInit类的initCache方法方法的逻辑也比较复杂解析spring boot项目的application.yml文件中jetcache.remote .${areaName}中的Redis配置创建Redis连接如果配置了集群模式则需要创建集群模式的Redis连接如果配置的是单节点模式则会创建单节点的Redis连接创建用于创建Lettuce类型的内存缓存的创建者RedisLettuceCacheBuilder并调用parseGeneralConfig方法解析JetCache的配置。最后将客户端和连接对象存入自动配置的自定义容器中并返回一个包含相关配置的ExternalCacheBuilder对象。源码如下
Override
protected CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix) {// 获取Lettuce缓存的URI配置MapString, Object map ct.subTree(uri/*there is no dot*/).getProperties();// 获取读取模式String readFromStr ct.getProperty(readFrom);String mode ct.getProperty(mode);// 获取异步结果超时时间long asyncResultTimeoutInMillis ct.getProperty(asyncResultTimeoutInMillis, CacheConsts.ASYNC_RESULT_TIMEOUT.toMillis());// 判断是否启用广播通道boolean enablePubSub parseBroadcastChannel(ct) ! null;ReadFrom readFrom null;// 根据读取模式字符串获取ReadFrom枚举类型if (readFromStr ! null) {readFrom ReadFrom.valueOf(readFromStr.trim());}AbstractRedisClient client;StatefulConnectionbyte[], byte[] connection;StatefulRedisPubSubConnectionbyte[], byte[] pubSubConnection null;// 判断是否配置了URIif (map null || map.size() 0) {// 如果未配置URI则抛出异常throw new CacheConfigException(lettuce uri is required);} else {// 将配置的URI转换为RedisURI对象列表ListRedisURI uriList map.values().stream().map((k) - RedisURI.create(URI.create(k.toString()))).collect(Collectors.toList());if (Cluster.equalsIgnoreCase(mode)) {// 配置为集群模式client RedisClusterClient.create(uriList);// 链接集群节点并获取连接对象connection clusterConnection(ct, readFrom, (RedisClusterClient) client, false);if (enablePubSub) {// 如果启用了广播通道则获取与集群节点的连接对象pubSubConnection (StatefulRedisPubSubConnection) clusterConnection(ct, readFrom, (RedisClusterClient) client, true);}} else {// 配置为单节点模式client RedisClient.create();((RedisClient) client).setOptions(ClientOptions.builder().disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS).build());// 链接单节点并获取连接对象StatefulRedisMasterReplicaConnection c MasterReplica.connect((RedisClient) client, new JetCacheCodec(), uriList);if (readFrom ! null) {// 如果指定了读取模式则设置连接对象的读取模式c.setReadFrom(readFrom);}connection c;if (enablePubSub) {// 如果启用了广播通道则获取与单节点的连接对象pubSubConnection ((RedisClient) client).connectPubSub(new JetCacheCodec(), uriList.get(0));}}}// 创建外部缓存构建器对象ExternalCacheBuilder externalCacheBuilder RedisLettuceCacheBuilder.createRedisLettuceCacheBuilder().connection(connection).pubSubConnection(pubSubConnection).redisClient(client).asyncResultTimeoutInMillis(asyncResultTimeoutInMillis);// 解析通用配置parseGeneralConfig(externalCacheBuilder, ct);// eg: remote.default.client// 将Redis客户端对象存入自动配置的自定义容器中autoConfigureBeans.getCustomContainer().put(cacheAreaWithPrefix .client, client);// 获取Lettuce连接管理器对象LettuceConnectionManager m LettuceConnectionManager.defaultManager();// 初始化Lettuce连接管理器m.init(client, connection);// 将Lettuce连接管理器中的连接对象存入自动配置的自定义容器中autoConfigureBeans.getCustomContainer().put(cacheAreaWithPrefix .connection, m.connection(client));// 将Lettuce连接管理器中的命令对象存入自动配置的自定义容器中autoConfigureBeans.getCustomContainer().put(cacheAreaWithPrefix .commands, m.commands(client));// 将Lettuce连接管理器中的异步命令对象存入自动配置的自定义容器中autoConfigureBeans.getCustomContainer().put(cacheAreaWithPrefix .asyncCommands, m.asyncCommands(client));// 将Lettuce连接管理器中的反应式命令对象存入自动配置的自定义容器中autoConfigureBeans.getCustomContainer().put(cacheAreaWithPrefix .reactiveCommands, m.reactiveCommands(client));// 返回外部缓存构建器对象return externalCacheBuilder;
}在上面的方法中如果配置的Redis配置是集群模式则会调用clusterConnection方法建立集群模式的Redis连接相应的源码如下
/*** 创建一个与Redis集群连接的状态保持连接对象。* param ct 配置树对象用于获取配置信息* param readFrom 读取来源用于设置连接的读取来源* param client Redis集群客户端对象* param pubsub 是否创建一个订阅连接* return 状态保持连接对象*/
private StatefulConnectionbyte[], byte[] clusterConnection(ConfigTree ct, ReadFrom readFrom, RedisClusterClient client, boolean pubsub) {int enablePeriodicRefresh ct.getProperty(enablePeriodicRefresh, 60);boolean enableAllAdaptiveRefreshTriggers ct.getProperty(enableAllAdaptiveRefreshTriggers, true);ClusterTopologyRefreshOptions.Builder topologyOptionBuilder ClusterTopologyRefreshOptions.builder();if (enablePeriodicRefresh 0) {topologyOptionBuilder.enablePeriodicRefresh(Duration.ofSeconds(enablePeriodicRefresh));}if (enableAllAdaptiveRefreshTriggers) {topologyOptionBuilder.enableAllAdaptiveRefreshTriggers();}ClusterClientOptions options ClusterClientOptions.builder().topologyRefreshOptions(topologyOptionBuilder.build()).disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS).build();client.setOptions(options);if (pubsub) {return client.connectPubSub(new JetCacheCodec());} else {StatefulRedisClusterConnectionbyte[], byte[] c client.connect(new JetCacheCodec());if (readFrom ! null) {c.setReadFrom(readFrom);}return c;}
}SpringDataRedisAutoInit
SpringDataRedisAutoInit继承自抽象类ExternalCacheAutoInitinitCache方法的实现比较简单先是获取RedisConnectionFactory的Bean如果有多个就获取jetCache配置中connectionFactory来决定使用哪一个RedisConnectionFactory实例创建用于创建Lettuce类型的内存缓存的创建者RedisLettuceCacheBuilder并调用parseGeneralConfig方法解析JetCache的配置。最后将客户端和连接对象存入自动配置的自定义容器中并返回一个包含相关配置的ExternalCacheBuilder对象。源码如下
/*** 初始化缓存** param ct 配置树* param cacheAreaWithPrefix 缓存区域名称包括前缀* return 缓存构建器*/
Override
protected CacheBuilder initCache(ConfigTree ct, String cacheAreaWithPrefix) {// 从应用上下文中获取 RedisConnectionFactory 的 bean 映射MapString, RedisConnectionFactory beans applicationContext.getBeansOfType(RedisConnectionFactory.class);// 如果 bean 映射为空或为空抛出异常if (beans null || beans.isEmpty()) {throw new CacheConfigException(no RedisConnectionFactory in spring context);}// 获取一个可用的 RedisConnectionFactory 实例RedisConnectionFactory factory beans.values().iterator().next();// 如果 Spring 上下文中有多个 RedisConnectionFactory抛出异常if (beans.size() 1) {String connectionFactoryName ct.getProperty(connectionFactory);// 如果 connectionFactoryName 为空抛出异常if (connectionFactoryName null) {throw new CacheConfigException(connectionFactory is required, because there is multiple RedisConnectionFactory in Spring context);}// 检查 bean 映射中是否包含指定的 connectionFactoryName如果不包含抛出异常if (!beans.containsKey(connectionFactoryName)) {throw new CacheConfigException(there is no RedisConnectionFactory named connectionFactoryName in Spring context);}// 使用指定的 connectionFactoryName 获取 RedisConnectionFactory 实例factory beans.get(connectionFactoryName);}// 创建一个 ExternalCacheBuilder 实例并使用 RedisSpringDataCacheBuilder 工具类创建构建器设置 connectionFactoryExternalCacheBuilder builder RedisSpringDataCacheBuilder.createBuilder().connectionFactory(factory);// 解析通用配置到构建器中parseGeneralConfig(builder, ct);// 返回构建器return builder;
}ExternalCacheAutoInit
类ExternalCacheAutoInit作为Redis缓存自动化初始类的父类实现逻辑还是比较简单的源码如下
/*** 外部缓存自动初始化抽象类*/
public abstract class ExternalCacheAutoInit extends AbstractCacheAutoInit {public ExternalCacheAutoInit(String... cacheTypes) {super(cacheTypes);}/*** 解析通用配置** param builder 缓存构建器* param ct 配置树*/Overrideprotected void parseGeneralConfig(CacheBuilder builder, ConfigTree ct) {super.parseGeneralConfig(builder, ct);ExternalCacheBuilder ecb (ExternalCacheBuilder) builder;ecb.setKeyPrefix(ct.getProperty(keyPrefix));ecb.setBroadcastChannel(parseBroadcastChannel(ct));ecb.setValueEncoder(new ParserFunction(ct.getProperty(valueEncoder, CacheConsts.DEFAULT_SERIAL_POLICY)));ecb.setValueDecoder(new ParserFunction(ct.getProperty(valueDecoder, CacheConsts.DEFAULT_SERIAL_POLICY)));}/*** 解析广播通道** param ct 配置树* return 解析后的广播通道若为空则返回null*/protected String parseBroadcastChannel(ConfigTree ct) {String broadcastChannel ct.getProperty(broadcastChannel);if (broadcastChannel ! null !.equals(broadcastChannel.trim())) {return broadcastChannel.trim();} else {return null;}}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/929996.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!