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統一管理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM