Въведение в JCache

1. Общ преглед

Просто казано, JCache е стандартният API за кеширане за Java. В този урок ще видим какво е JCache и как можем да го използваме.

2. Зависимости на Maven

За да използваме JCache, трябва да добавим следната зависимост към нашия pom.xml :

 javax.cache cache-api 1.0.0-PFD 

Имайте предвид, че можем да намерим най-новата версия на библиотеката в Централното хранилище на Maven.

Също така трябва да добавим изпълнение на API към нашия pom.xml ; ще използваме Hazelcast тук:

 com.hazelcast hazelcast 3.9-EA 

Също така можем да намерим най-новата версия на Hazelcast в централното хранилище на Maven.

3. Реализации на JCache

JCache се реализира от различни кеширащи решения:

  • Реализация на JCache Reference
  • Леска
  • Кохерентност на Oracle
  • Теракот Ehcache
  • Инфиниспан

Имайте предвид, че за разлика от други референтни реализации, не се препоръчва използването на JCache Reference Implementation в производството, тъй като причинява някои проблеми с паралелността.

4. Основни компоненти

4.1. Кеш памет

Интерфейсът на кеша има следните полезни методи:

  • get () - взема ключът на елемент като параметър и връща стойността на елемента; връща null, ако ключът не съществува в кеша
  • getAll () - множество ключове могат да бъдат предадени на този метод като Set; т той метод връща дадените ключовете и свързаните с тях ценности като Карта
  • getAndRemove () - методът извлича стойност с помощта на своя ключ и премахва елемента от кеша
  • put () - вмъква нов елемент в кеша
  • clear () - премахва всички елементи в кеша
  • containsKey () - проверява дали кешът съдържа определен ключ

Както виждаме, имената на методите са почти обясними. За повече информация относно тези и други методи, посетете Javadoc.

4.2. CacheManager

CacheManager е един от най-важните интерфейси на API. Позволява ни да установяваме, конфигурираме и затваряме кешове .

4.3. CachingProvider

CachingProvider е интерфейс, който ни позволява да създаваме и управляваме жизнения цикъл на CacheManagers .

4.4. Конфигурация

Конфигурацията е интерфейс, който ни позволява да конфигурираме кешовете . Той има едно конкретно изпълнение - MutableConfiguration и подинтерфейс - CompleteConfiguration .

5. Създаване на кеш памет

Нека да видим как можем да създадем прост кеш :

CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); MutableConfiguration config = new MutableConfiguration(); Cache cache = cacheManager .createCache("simpleCache", config); cache.put("key1", "value1"); cache.put("key2", "value2"); cacheManager.close();

Всичко, което правим е:

  • Създаване на обект CachingProvider , който използваме за конструиране на обект CacheManager
  • Създаване на обект MutableConfiguration , който е изпълнение на интерфейса за конфигуриране
  • Създаване на обект Cache с помощта на обекта CacheManager, който създадохме по-рано
  • Поставяйки всички записи, трябва да кешираме в нашия обект Cache
  • Затваряне на CacheManager, за да освободи ресурсите, използвани от кеша

Ако не предоставим никаква реализация на JCache в нашия pom.xml , ще се появи следното изключение:

javax.cache.CacheException: No CachingProviders have been configured

Причината за това е, че JVM не можа да намери конкретна реализация на метода getCacheManager () .

6. EntryProcessor

EntryProcessor ни позволява да модифицираме записите в кеша , използвайки атомни операции, без да се налага да ги добавяме отново в кеша . За да го използваме, трябва да внедрим интерфейса EntryProcessor :

public class SimpleEntryProcessor implements EntryProcessor, Serializable { public String process(MutableEntry entry, Object... args) throws EntryProcessorException { if (entry.exists()) { String current = entry.getValue(); entry.setValue(current + " - modified"); return current; } return null; } }

Сега, нека използваме нашата реализация на EntryProcessor :

@Test public void whenModifyValue_thenCorrect() { this.cache.invoke("key", new SimpleEntryProcessor()); assertEquals("value - modified", cache.get("key")); }

7. Слушатели на събития

Слушателите на събития ни позволяват да предприемаме действия при задействане на който и да е от типовете събития, дефинирани в преброяването на EventType , които са:

  • СЪЗДАДЕН
  • АКТУАЛИЗИРАН
  • ПРЕМАХВАН
  • ПРОСРОЧЕН

Първо, трябва да приложим интерфейси на събитията, които ще използваме.

Например, ако искаме да използваме CREATED и UPDATED типовете събития, тогава трябва да реализираме интерфейсите CacheEntryCreatedListener и CacheEntryUpdatedListener .

Да видим пример:

public class SimpleCacheEntryListener implements CacheEntryCreatedListener, CacheEntryUpdatedListener, Serializable { private boolean updated; private boolean created; // standard getters public void onUpdated( Iterable
    
      events) throws CacheEntryListenerException { this.updated = true; } public void onCreated( Iterable
     
       events) throws CacheEntryListenerException { this.created = true; } }
     
    

Сега, нека пуснем нашия тест:

@Test public void whenRunEvent_thenCorrect() throws InterruptedException { this.listenerConfiguration = new MutableCacheEntryListenerConfiguration( FactoryBuilder.factoryOf(this.listener), null, false, true); this.cache.registerCacheEntryListener(this.listenerConfiguration); assertEquals(false, this.listener.getCreated()); this.cache.put("key", "value"); assertEquals(true, this.listener.getCreated()); assertEquals(false, this.listener.getUpdated()); this.cache.put("key", "newValue"); assertEquals(true, this.listener.getUpdated()); }

8. CacheLoader

CacheLoader ни позволява да използваме режим за четене, за да третираме кеша като основно хранилище на данни и да четем данни от него .

В реален сценарий можем да накараме кеша да чете данни от действителното съхранение.

Нека да разгледаме един пример. Първо, трябва да внедрим интерфейса CacheLoader :

public class SimpleCacheLoader implements CacheLoader { public String load(Integer key) throws CacheLoaderException { return "fromCache" + key; } public Map loadAll(Iterable keys) throws CacheLoaderException { Map data = new HashMap(); for (int key : keys) { data.put(key, load(key)); } return data; } }

И сега, нека използваме нашата реализация на CacheLoader :

public class CacheLoaderTest { private Cache cache; @Before public void setup() { CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); MutableConfiguration config = new MutableConfiguration() .setReadThrough(true) .setCacheLoaderFactory(new FactoryBuilder.SingletonFactory( new SimpleCacheLoader())); this.cache = cacheManager.createCache("SimpleCache", config); } @Test public void whenReadingFromStorage_thenCorrect() { for (int i = 1; i < 4; i++) { String value = cache.get(i); assertEquals("fromCache" + i, value); } } }

9. Заключение

В този урок видяхме какво е JCache и разгледахме някои от важните му характеристики в няколко практически сценария.

Както винаги, пълното изпълнение на този урок може да бъде намерено в GitHub.