• ehcache3-jcache


    原生的ehcache只需关注CacheManager和Cache即可,而jcache多了一个cachingProvider,其是用来发现cachingProvider实现的,比如ehcache的EhcacheCachingProvider,然后再通过特定实现的CachingProvider得到特定实现的CacheManager。总的来说,关键就是得到合适cachingProvider,之后就与特定的cache框架耦合了。
     
    ehcache的xml配置
     1 <config
     2     xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
     3     xmlns='http://www.ehcache.org/v3'
     4     xsi:schemaLocation="
     5         http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd">
     6 
     7   <cache alias="ready-cache">
     8     <key-type>java.lang.Long</key-type>
     9     <value-type>com.pany.domain.Product</value-type>
    10     <loader-writer>
    11       <class>com.pany.ehcache.integration.ProductCacheLoaderWriter</class>
    12     </loader-writer>
    13     <heap unit="entries">100</heap>
    14   </cache>
    15 
    16 </config>

    ehcache的jcache api

    1 //如果依赖中有多个jcache实现,这里可以指定ehcache实现Caching.getCachingProvider(“org.ehcache.jsr107.EhcacheCachingProvider”);,如果只有一个jcache实现,则Caching.getCachingProvider()可以找到对应的实现,查找逻辑后面有提到
    2 CachingProvider cachingProvider = Caching.getCachingProvider();
    3 //getCacheManager第一个参数为一个uri,对于ehcache来说该uri应该是ehcache的配置文件,ehcache实现在这里就会初始化配置文件中的cache
    4         CacheManager manager = cachingProvider.getCacheManager(
    5                 getClass().getResource("/org/ehcache/docs/ehcache-jsr107-config.xml").toURI(),
    6                 getClass().getClassLoader());
    7 //从manager获得已配置的cache
    8         Cache<Long, Product> readyCache = manager.getCache("ready-cache", Long.class, Product.class);

    下面就来看一下ehcache是如何适配jcache的。

    getCachingProvider:

    getCachingProviders的主要逻辑:
     1 public synchronized Iterable<CachingProvider> getCachingProviders(ClassLoader classLoader) {
     2 
     3   final ClassLoader serviceClassLoader = classLoader == null ? getDefaultClassLoader() : classLoader;
     4   LinkedHashMap<String, CachingProvider> providers = cachingProviders.get(serviceClassLoader);
     5 
     6   if (providers == null) {
     7         //如果系统参数中设置了javax.cache.spi.CachingProvider相关值,则加载该值对应的类
     8     if (System.getProperties().containsKey(JAVAX_CACHE_CACHING_PROVIDER)) {
     9       String className = System.getProperty(JAVAX_CACHE_CACHING_PROVIDER);
    10       providers = new LinkedHashMap<String, CachingProvider>();
    11       providers.put(className, loadCachingProvider(className, serviceClassLoader));
    12 
    13     } else {
    14       providers = AccessController.doPrivileged(new PrivilegedAction<LinkedHashMap<String, CachingProvider>>() {
    15         @Override
    16         public LinkedHashMap<String, CachingProvider> run() {
    17           LinkedHashMap<String, CachingProvider> result = new LinkedHashMap<String, CachingProvider>();
    18                     //ServiceLoader.load会lazy加载所以符合条件的类
    19           ServiceLoader<CachingProvider> serviceLoader = ServiceLoader.load(CachingProvider.class, serviceClassLoader);
    20           //这里serviceLoader.iterator().next()会真正进行加载,
    21           //如果依赖中包含多个jcache实现,最终的result就会有多个元素
    22           for (CachingProvider provider : serviceLoader) {
    23             result.put(provider.getClass().getName(), provider);
    24           }
    25           return result;
    26         }
    27       });
    28 
    29     }
    30 
    31     cachingProviders.put(serviceClassLoader, providers);
    32   }
    33 
    34   return providers.values();
    35 }
    ServiceLoader.load的主要逻辑:

    注意,Class的getResource的路径可以以“/”开头,以“/”开头代表相对于运行环境的根路径(通常是com的父目录),不以“/”开头代表相对于该Class所在路径的路径;而ClassLoader的getResource的路径不能以“/”开头,与Class以“/”开头类似。
     
    ehcache类库下的META-INF/services/

     打开该文件,发现ehcache的cachingProvider实现类的全限定名:

    CachingProvider.getCacheManager有这样一个重载方法,将ehcache配置文件路径传入uri即可,这样ehcache就可以使用jcache的api,并使用自己的配置文件了:

    总结一下,Caching.getCachingProvider会去找特定的配置文件META-INF/services/javax.cache.spi.CachingProvider,特定的实现会在该文件内写入CachingProvider实现类的全限定名,Caching.getCachingProvider得到类名后就可以加载该类,最终返回特定实现的CachingProvider,如EhcacheCachingProvider,再之后就是Ehcache的事了。

    为什么要有CachingProvider呢?jcache直接提供CacheManager的api不行吗?我觉得是可以的,只不过没有了CachingProvider就没有了对CacheManager的统一管理,我们来看CachingProvider接口,它提供了get(获取CacheManager)、close(关闭CacheManager)的方法,这样我们就可以对CacheManager统一管理。

  • 相关阅读:
    git 查看、创建、切换、删除、重命名和推送分支
    Java 构造器或构造方法
    Java 二维数组
    Java 引用类型数组
    Java this关键字
    STM8S103 PB4和PB5
    RK3288 dts文件中背光配置参数
    Laravel Cache 缓存钉钉微应用的 Access Token
    Laravel View Composer
    Laravel Cache 的缓存文件在到期后是否会自动删除
  • 原文地址:https://www.cnblogs.com/holoyong/p/7263140.html
Copyright © 2020-2023  润新知