spring boot 源码解析34-spring boot集成spring cache(基于EHcache)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

前言

本文在上篇文章的基础上做出修改,使其使用Ehcache.

Ehcache集成

  1. 在pom文件中加入如下配置:

        
            net.sf.ehcache
            ehcache
        
  2. 在src/main/resources 目录下加入ehcache.xml.代码如下:

        
        
    
        
        
        
    
        
        
        
        
        
             
        
    
         
         
         
          

    关于Ehcache的配置,可参考如下链接:

    Ehcache整合spring配置

    Ehcache配置详解及CacheManager使用

    此时,我们就修改好了,这也能够体验到spring cache 的威力,不依赖于底层实现.

自动装配

EhCacheCacheManager的自动装配是在EhCacheCacheConfiguration中.

这里先提1个问题,spring boot 中默认支持的是ConcurrentMapCacheManager,现在我们再加入ehcache的依赖,不就有两个了吗? 这样有问题吗?

答案: 不会.原因如下:

  1. chche的自动装配的总入口是在CacheAutoConfiguration中,该类通过@Import(CacheConfigurationImportSelector.class) 导入了CacheConfigurationImportSelector. 由于该类是ImportSelector的类型,因此会执行其selectImports方法,将其返回值接着调用ConfigurationClassParser#processImports处理.其selectImports代码如下:

        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
                    CacheType[] types = CacheType.values();
                    String[] imports = new String[types.length];
                    for (int i = 0; i < types.length; i++) {
                        imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
                    }
                    return imports;
        }

    遍历CacheType的枚举集合,依次获得其对应的配置类,加入到imports中 最后的返回值如下:

    1. GenericCacheConfiguration.class
    2. JCacheCacheConfiguration.class
    3. EhCacheCacheConfiguration.class
    4. HazelcastCacheConfiguration.class
    5. InfinispanCacheConfiguration.class
    6. CouchbaseCacheConfiguration
    7. RedisCacheConfiguration
    8. CaffeineCacheConfiguration
    9. GuavaCacheConfiguration
    10. SimpleCacheConfiguration
    11. NoOpCacheConfiguration
  2. 对于 GenericCacheConfiguration来说,其注解如下:

        @Configuration
        @ConditionalOnBean(Cache.class)
        @ConditionalOnMissingBean(CacheManager.class)
        @Conditional(CacheCondition.class)

    该类会生效.

  3. 对于 JCacheCacheConfiguration, HazelcastCacheConfiguration,… GuavaCacheConfiguration来说,都需要其相关的类在类路径下存在. 因此,在默认情况下在PARSE_CONFIGURATION阶段生效的配置有:

    GenericCacheConfiguration, EhCacheCacheConfiguration, SimpleCacheConfiguration,NoOpCacheConfiguration

  4. 最后,执行ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass(ConfigurationClass, TrackedConditionEvaluator)时:

    1. GenericCacheConfiguration: 由于@ConditionalOnBean(Cache.class)是在REGISTER_BEAN阶段时执行并且在beanFactory中不存在Cache类型的bean.因此该类不进行注册.证明:查询/autoconfig,其中有关GenericCacheConfiguration的结果如下:

          GenericCacheConfiguration: {
          notMatched: [
          {
          condition: "OnBeanCondition",
          message: "@ConditionalOnBean (types: org.springframework.cache.Cache; SearchStrategy: all) did not find any beans"
          }
          ],
          matched: [
          {
          condition: "CacheCondition",
          message: "Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type"
          }
          ]
          }
    2. RedisCacheConfiguration:同样,不满足@ConditionalOnBean(RedisTemplate.class)的条件,因此不会执行注册.证明:查询/autoconfig,其中有关GenericCacheConfiguration的结果如下:

          RedisCacheConfiguration: {
          notMatched: [
          {
          condition: "OnBeanCondition",
          message: "@ConditionalOnBean (types: org.springframework.data.redis.core.RedisTemplate; SearchStrategy: all) did not find any beans"
          }
          ],
          matched: [
          {
          condition: "CacheCondition",
          message: "Cache org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration automatic cache type"
          }
          ]
          }
    3. SimpleCacheConfiguration–> 不满足@ConditionalOnMissingBean(CacheManager.class)条件(因为EhCacheCacheConfiguration中配置了),证明:

          {
          notMatched: [
          {
          condition: "OnBeanCondition",
          message: "@ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) found bean 'cacheManager'"
          }
          ],
          matched: [
          {
          condition: "CacheCondition",
          message: "Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type"
          }
          ]
          }
    4. NoOpCacheConfiguration–> 不满足@ConditionalOnMissingBean(CacheManager.class)条件(因为EhCacheCacheConfiguration中配置了),证明:

          NoOpCacheConfiguration: {
          notMatched: [
          {
          condition: "OnBeanCondition",
          message: "@ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) found bean 'cacheManager'"
          }
          ],
          matched: [
          {
          condition: "CacheCondition",
          message: "Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration automatic cache type"
          }
          ]

    因此,最后生效的是EhCacheCacheManager

  5. 回到正题上来,EhCacheCacheConfiguration有如下注解:

        @Configuration
        @ConditionalOnClass({ Cache.class, EhCacheCacheManager.class })
        @ConditionalOnMissingBean(org.springframework.cache.CacheManager.class)
        @Conditional({ CacheCondition.class,
                EhCacheCacheConfiguration.ConfigAvailableCondition.class })
    • @Configuration –> 配置类
    • @ConditionalOnClass({ Cache.class, EhCacheCacheManager.class })–> 在当前类路径下存在 Cache.class, EhCacheCacheManager.class 时生效
    • @ConditionalOnMissingBean(org.springframework.cache.CacheManager.class)–> beanFactory中不存在org.springframework.cache.CacheManager类型的bean时生效
    • @Conditional({ CacheCondition.class,
      EhCacheCacheConfiguration.ConfigAvailableCondition.class })–>

      1. CacheCondition –> 默认返回true,我们在上篇文章中分析过了
      2. EhCacheCacheConfiguration.ConfigAvailableCondition–> 如果配置有spring.cache.ehcache.config 则返回匹配,或者 如果在类路径下存在ehcache.xml则返回匹配.由于我们在类路径下创建了ehcache.xml,因此,返回匹配.
  6. 在该类中声明了2个@Bean方法:

    1. ehCacheCacheManager,代码如下:

          @Bean
          @ConditionalOnMissingBean
          public CacheManager ehCacheCacheManager() {
              Resource location = this.cacheProperties
                      .resolveConfigLocation(this.cacheProperties.getEhcache().getConfig());
              if (location != null) {
                  return EhCacheManagerUtils.buildCacheManager(location);
              }
              return EhCacheManagerUtils.buildCacheManager();
          }
      • @Bean –> 注册1个id为ehCacheCacheManager,类型为CacheManager的bean
      • @ConditionalOnMissingBean–> 当BeanFactory中不存在CacheManager类型的bean时生效

      该方法的逻辑如下:

      1. 获得spring.cache.ehcache.config 配置的路径
      2. 如果配置了,则加载指定的路径创建CacheManager,否则,读取默认EhCache的文件路径:/ehcache.xml,/ehcache-failsafe.xml

      由于我们没有配置spring.cache.ehcache.config,因此会读取ehcache.xml

    2. cacheManager,代码如下:

          @Bean
          public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
              return this.customizers.customize(new EhCacheCacheManager(ehCacheCacheManager));
          }
      • @Bean –> 注册1个id为cacheManager,类型为EhCacheCacheManager的bean

      方法的逻辑如下:

      1. 实例化EhCacheCacheManager
      2. 根据CacheManagerCustomizers来做个性化配置.由于spring boot 没有装配CacheManagerCustomizer,因此该方法相当于空操作.

来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring boot 源码解析34-spring boot集成spring cache(基于EHcache)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏