• spring cache (ehcache方式)



    前置

    会演示springcache的使用方式
    项目地址

    前置配置

    本篇文章是基于上篇文章进行: spring cache (默认方式)

    强调:

    在追踪源码的时候发现, 是通过注入ehCacheCacheManager进行文件的初始化, 当然解析xml文件也是该地方开始. 也就有了MyEhCacheCacheConfiguration,java方法. 大致思路同源码一致, 只是对获取的数据进行拦截, 增加部分数据, 进行一遍赋值操作

    源码部分
    spring cache (默认方式) 一致, 只是实现缓存的方式不一样

    关键类: org.springframework.cache.Cache
    org.springframework.cache.interceptor.CacheInterceptor#invoke
    org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
    实现类: org.springframework.cache.ehcache.EhCacheCache

    相关缓存文章

    spring cache (默认方式)
    spring cache (Redis方式)
    spring cache (ehcache方式)


    pom: jar

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    
    <dependency>
    	<groupId>net.sf.ehcache</groupId>
    	<artifactId>ehcache</artifactId>
    </dependency>
    
    <dependency>
    	<groupId>javax.cache</groupId>
    	<artifactId>cache-api</artifactId>
    </dependency>
    
    <!-- 反射工具包 -->
    <dependency>
    	<groupId>org.reflections</groupId>
    	<artifactId>reflections</artifactId>
    	<version>0.9.10</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    配置文件:

    ehcache.xml

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
    
        
        <diskStore path="F:\upload\EhCache"/>
    
        
    
    
        
        <defaultCache
                eternal="true"
                maxElementsInMemory="1000"
                overflowToDisk="false"
                diskPersistent="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="0"
                memoryStoreEvictionPolicy="LRU"/>
    
        
        
        <cache
                name="CUSTOMIZE_GLOBAL"
                eternal="true"
                maxElementsInMemory="1000"
                overflowToDisk="false"
                diskPersistent="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="0"
                memoryStoreEvictionPolicy="LRU"/>
    
    
    ehcache>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    application.yml

    spring:
      cache:
        # 程序启动时创建的缓存名称
        cache-names: chaim-name
        # 缓存类型 org.springframework.boot.autoconfigure.cache.CacheType
        type: ehcache
        ehcache:
          config: classpath:ehcache.xml
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    MyEhCacheCacheConfiguration.java

    package com.chaim.spring.cache.ehcache.config;
    
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.config.CacheConfiguration;
    import net.sf.ehcache.config.Configuration;
    import org.reflections.Reflections;
    import org.reflections.scanners.MethodAnnotationsScanner;
    import org.reflections.util.ClasspathHelper;
    import org.reflections.util.ConfigurationBuilder;
    import org.springframework.boot.autoconfigure.cache.CacheProperties;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.cache.ehcache.EhCacheManagerUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * @author Chaim
     * @date 2022/9/23 0:11
     */
    @Component
    @Primary
    public class MyEhCacheCacheConfiguration {
        /**
         * 固定 ehcache.xml 中 cache标签name值为: CACHE_NAME 就进行全局配置
         */
        private static final String CACHE_NAME = "CUSTOMIZE_GLOBAL";
        /**
         * 要扫描注解的包路径
         */
        private static final String PACKAGE_NAME = "com.chaim.spring.cache.ehcache.controller";
    
        /**
         * 重写 org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration#ehCacheCacheManager
         * 实现: 多 cache 标签自动添加
         *
         * @param cacheProperties
         * @return
         */
        @Bean
        CacheManager ehCacheCacheManager(CacheProperties cacheProperties) {
            Resource location = cacheProperties.resolveConfigLocation(cacheProperties.getEhcache().getConfig());
            if (location != null) {
                // 源码: 从给定资源中解析 EhCache 配置,以供进一步使用
                Configuration configuration = EhCacheManagerUtils.parseConfiguration(location);
                // 对获取的 ehcache 资源进行重写
                Map<String, CacheConfiguration> cacheConfigurations = configuration.getCacheConfigurations();
                // 校验其是否是全局标签 (配置该标签, 就标记需要缓存的都是此一个文件进行加载)
                CacheConfiguration cacheConfiguration = cacheConfigurations.get(CACHE_NAME);
                if (cacheConfiguration != null) {
                    // 获取指定路径下的 @Cacheable 的 value 值, 也就是需要进行创建的缓存文件名
                    Set<String> allCacheableValue = this.getAllCacheableValue();
                    allCacheableValue.forEach(key -> {
                        if (cacheConfigurations.get(key) == null) {
                            // 对象克隆, 该处涉及深浅拷贝
                            CacheConfiguration clone = cacheConfiguration.clone();
                            // 修改缓存文件名为 @Cacheable 的 value 值
                            clone.name(key);
                            // 将需要的值 PUT 进入 CacheConfiguration, 对应的cache标签值除name其余不变
                            cacheConfigurations.put(key, clone);
                        }
                    });
                    // 移除全局配置配置文件, 避免创建该文件无效
                    cacheConfigurations.remove(CACHE_NAME);
                }
                // 源码: 返回CacheManager
                return new CacheManager(configuration);
            }
            return EhCacheManagerUtils.buildCacheManager();
        }
    
        /**
         * 获取指定路径下所有 Cacheable 的 value 值
         *
         * @return Cacheable -> value
         */
        private Set<String> getAllCacheableValue() {
            Set<String> set = new HashSet<>();
    
            // 要扫描的包
            ConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
                    .addUrls(ClasspathHelper.forPackage(PACKAGE_NAME))
                    .addScanners(new MethodAnnotationsScanner());
            Reflections ref = new Reflections(configurationBuilder);
    
            // 获取扫描到的标记注解的集合
            Set<Method> methodsAnnotatedWith = ref.getMethodsAnnotatedWith(Cacheable.class);
            for (Method method : methodsAnnotatedWith) {
                Cacheable cacheable = method.getAnnotation(Cacheable.class);
                String[] value = cacheable.value();
                set.addAll(Arrays.asList(value));
            }
            return set;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    效果图

    禁用 MyEhCacheCacheConfiguration.java

    在这里插入图片描述


    启用 MyEhCacheCacheConfiguration.java

    在这里插入图片描述

  • 相关阅读:
    【verilog 设计】 reg有没有必要全部赋初值?
    【C++】双向带头循环链表~~看似结构最复杂但是实现超简单
    图像修复论文阅读笔记-----Globally and Locally Consistent Image Completion
    18. Spring类型转换之ConversionService
    武汉科技大学2023考研真题笔记资料应该从哪里找?
    87、一文带你了解网络操作系统,除了windows、linux,还有你没听过的
    vue中解决一个部门不能选择的问题
    唯品会电商api接口
    SICP:惰性求值、流和尾递归(Python实现)
    硬盘格式化了怎么恢复数据
  • 原文地址:https://blog.csdn.net/qq_38637558/article/details/127944668