cache2k и Generic T не играют хорошо вместе
В руководстве пользователя cache2k, §2.3 . Cache Aside содержит пример кода и предложение о кэшировании.
Cache<String, String> routeToAirline = new Cache2kBuilder<String, String>() {} .name("routeToAirline") .build(); private String findFavoriteAirline(String origin, String destination) { // expensive operation to find the best airline for this route // for example, ask all friends... } public String lookupFavoirteAirline(String origin, String destination) { String route = origin + "-" + destination; String airline = routeToAirline.peek(route); if (airline == null) { airline = findFavoriteAirline(origin, destination); routeToAirline.put(route, airline); } return airline; }
Вышеприведенный шаблон называется кэшем в стороне.
И я как "Отлично.... Я люблю шаблон Cache Aside". Поэтому я пытаюсь реализовать один, используя дженерики вместо жесткого кодирования типа (значения).
Я придумал это, используя дженерики. И я внедряю метод, который "получает" товар (Поставщик). Полностью повторно используемый код!
package mypackage;
import java.util.function.Supplier;
import org.cache2k.Cache;
import org.cache2k.Cache2kBuilder;
//import mypackage.interfaces.IGenericCacheAside;
public class Cache2kGenericCacheAside<TEntity> ////implements IGenericCacheAside<TEntity> {
public final String CacheKeyPrefix = "GenericCacheAsidePrefix";
private volatile Cache<String, TEntity> theCache = null; /* static not allowed for TEntity */
public TEntity GetCacheAsideItem(String uniqueIdentifier, long itemLifeMiliseconds,
final Supplier<TEntity> valueFactory) {
this.initiateCacheObject();
String cacheKey = this.GetFullCacheKey(uniqueIdentifier);
TEntity cachedOrFreshItem = this.GetFromCache(cacheKey, itemLifeMiliseconds, valueFactory);
return cachedOrFreshItem;
}
public TEntity RemoveCacheAsideItem(String uniqueIdentifier) {
TEntity removedItem = null;
String cacheKey = this.GetFullCacheKey(uniqueIdentifier);
if (this.theCache.containsKey(uniqueIdentifier)) {
removedItem = this.theCache.peekAndRemove(cacheKey);
}
return removedItem;
}
private void initiateCacheObject(/* long duration, TimeUnit tu, long capacity */) {
if (null == this.theCache) {
theCache = new Cache2kBuilder<String, TEntity>() {
}.name("myCache").eternal(true).build();
}
}
private TEntity GetFromCache(String cacheKey, long millis, final Supplier<TEntity> valueFactory) {
TEntity cachedOrFreshItem = theCache.peek(cacheKey);
if (cachedOrFreshItem == null) {
cachedOrFreshItem = valueFactory.get();
theCache.put(cacheKey, cachedOrFreshItem);
theCache.expireAt(cacheKey, millis);
}
return cachedOrFreshItem;
}
private String GetFullCacheKey(String uniqueIdentifier) {
String returnValue = CacheKeyPrefix + uniqueIdentifier;
return returnValue;
}
}
Я получаю ошибку во время выполнения:
java.lang.IllegalArgumentException: тип времени выполнения недоступен, получил: TEntity
Я думаю, что я, возможно, наткнулся на этот ранее неизвестный мир стирания типов.
Есть ли способ реализовать этот код Generic-CacheAside? Этот скрытый драгоценный камень (стирание) ужасен.
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-api</artifactId>
<version>1.2.0.Final</version>
</dependency>
APPEND:
Вот пример. По сути, в любое время мне нужно кэшировать "что-то", которое не управляется параметром для извлечения. В моем примере ниже я кеширую SystemSetting (s). Нет параметра для управления поиском.
private static int NewedUpCounter = 0;
private static int CurrentRunCacheReads = 0;
private static void RunCacheAsideStuff() {
/* example ONLY. use construction-injection for "real" code */
////IGenericCacheAside<Collection<SystemSetting>> igca = new Cache2kGenericCacheAside<Collection<SystemSetting>>();
/* or */
Cache2kGenericCacheAside<Collection<SystemSetting>> igca = new Cache2kGenericCacheAside<Collection<SystemSetting>>();
for (int i = 0; i < 20; i++) {
/* in the below, it shows how the "time to keep in the cache" might change over time */
int cacheMilliseconds = 2500 + (500 * i);
System.out.println(String.format(" cacheMilliseconds=%1s",
cacheMilliseconds));
Collection<SystemSetting> cacheAsideSettings = igca.GetCacheAsideItem("myuniqueIdentifier", cacheMilliseconds,
TimeUnit.MILLISECONDS, App::CreateDummySystemSettings);
if (null != cacheAsideSettings) {
System.out.println("--------------");
System.out.println(String.format(" CurrentRunCacheReads=%1s",
++CurrentRunCacheReads));
System.out.println(String.format(" Cached Collection<SystemSetting> Read .. size=%1s",
cacheAsideSettings.size()));
for (SystemSetting sett : cacheAsideSettings) {
System.out.println(String.format(
"cacheAsideSettings !! SystemSetting.Key=%1s, SystemSetting.Value = %2s, i = %3s , Time= %4s",
sett.getSystemSettingKey(), sett.getSettingValue(), i, LocalDateTime.now()));
}
System.out.println("--------------");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(String.format("NewedUpCounter=%1s",
NewedUpCounter));
}
private static Collection<SystemSetting> CreateDummySystemSettings() {
NewedUpCounter++;
CurrentRunCacheReads=0;
long LOWER_RANGE = 10000; // assign lower range value
long UPPER_RANGE = 20000; // assign upper range value
Random random = new Random();
long randomValue = LOWER_RANGE + (long) (random.nextDouble() * (UPPER_RANGE - LOWER_RANGE));
Collection<SystemSetting> returnItems = new ArrayList<>();
for (int i = 101; i < 104; i++) {
SystemSetting newSetting = new SystemSetting();
newSetting.setSystemSettingKey(i);
newSetting.setSettingValue(String.format("ValueOf%1s*", randomValue));
returnItems.add(newSetting);
}
System.out.println(String.format("NEW Collection<SystemSetting> CREATED !! size=%1s ************************************************", returnItems.size()));
return returnItems;
}
И выходной. Образец, который показывает элемент / время в кэше, может измениться.
cacheMilliseconds=2500
NEW Collection<SystemSetting> CREATED !! size=3 ************************************************
--------------
CurrentRunCacheReads=1
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14000*, i = 0 , Time= 2018-09-28T13:04:14.043
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14000*, i = 0 , Time= 2018-09-28T13:04:14.052
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14000*, i = 0 , Time= 2018-09-28T13:04:14.052
--------------
cacheMilliseconds=3000
--------------
CurrentRunCacheReads=2
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14000*, i = 1 , Time= 2018-09-28T13:04:15.052
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14000*, i = 1 , Time= 2018-09-28T13:04:15.053
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14000*, i = 1 , Time= 2018-09-28T13:04:15.053
--------------
cacheMilliseconds=3500
--------------
CurrentRunCacheReads=3
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14000*, i = 2 , Time= 2018-09-28T13:04:16.054
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14000*, i = 2 , Time= 2018-09-28T13:04:16.054
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14000*, i = 2 , Time= 2018-09-28T13:04:16.054
--------------
cacheMilliseconds=4000
NEW Collection<SystemSetting> CREATED !! size=3 ************************************************
--------------
CurrentRunCacheReads=1
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17155*, i = 3 , Time= 2018-09-28T13:04:17.055
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17155*, i = 3 , Time= 2018-09-28T13:04:17.055
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17155*, i = 3 , Time= 2018-09-28T13:04:17.055
--------------
cacheMilliseconds=4500
--------------
CurrentRunCacheReads=2
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17155*, i = 4 , Time= 2018-09-28T13:04:18.056
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17155*, i = 4 , Time= 2018-09-28T13:04:18.056
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17155*, i = 4 , Time= 2018-09-28T13:04:18.056
--------------
cacheMilliseconds=5000
--------------
CurrentRunCacheReads=3
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17155*, i = 5 , Time= 2018-09-28T13:04:19.057
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17155*, i = 5 , Time= 2018-09-28T13:04:19.058
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17155*, i = 5 , Time= 2018-09-28T13:04:19.058
--------------
cacheMilliseconds=5500
--------------
CurrentRunCacheReads=4
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17155*, i = 6 , Time= 2018-09-28T13:04:20.058
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17155*, i = 6 , Time= 2018-09-28T13:04:20.058
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17155*, i = 6 , Time= 2018-09-28T13:04:20.058
--------------
cacheMilliseconds=6000
NEW Collection<SystemSetting> CREATED !! size=3 ************************************************
--------------
CurrentRunCacheReads=1
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 7 , Time= 2018-09-28T13:04:21.059
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 7 , Time= 2018-09-28T13:04:21.060
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 7 , Time= 2018-09-28T13:04:21.060
--------------
cacheMilliseconds=6500
--------------
CurrentRunCacheReads=2
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 8 , Time= 2018-09-28T13:04:22.060
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 8 , Time= 2018-09-28T13:04:22.060
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 8 , Time= 2018-09-28T13:04:22.060
--------------
cacheMilliseconds=7000
--------------
CurrentRunCacheReads=3
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 9 , Time= 2018-09-28T13:04:23.060
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 9 , Time= 2018-09-28T13:04:23.060
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 9 , Time= 2018-09-28T13:04:23.060
--------------
cacheMilliseconds=7500
--------------
CurrentRunCacheReads=4
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 10 , Time= 2018-09-28T13:04:24.060
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 10 , Time= 2018-09-28T13:04:24.061
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 10 , Time= 2018-09-28T13:04:24.061
--------------
cacheMilliseconds=8000
--------------
CurrentRunCacheReads=5
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 11 , Time= 2018-09-28T13:04:25.061
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 11 , Time= 2018-09-28T13:04:25.061
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 11 , Time= 2018-09-28T13:04:25.061
--------------
cacheMilliseconds=8500
--------------
CurrentRunCacheReads=6
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf17444*, i = 12 , Time= 2018-09-28T13:04:26.063
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf17444*, i = 12 , Time= 2018-09-28T13:04:26.063
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf17444*, i = 12 , Time= 2018-09-28T13:04:26.064
--------------
cacheMilliseconds=9000
NEW Collection<SystemSetting> CREATED !! size=3 ************************************************
--------------
CurrentRunCacheReads=1
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 13 , Time= 2018-09-28T13:04:27.065
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 13 , Time= 2018-09-28T13:04:27.065
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 13 , Time= 2018-09-28T13:04:27.066
--------------
cacheMilliseconds=9500
--------------
CurrentRunCacheReads=2
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 14 , Time= 2018-09-28T13:04:28.066
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 14 , Time= 2018-09-28T13:04:28.066
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 14 , Time= 2018-09-28T13:04:28.066
--------------
cacheMilliseconds=10000
--------------
CurrentRunCacheReads=3
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 15 , Time= 2018-09-28T13:04:29.067
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 15 , Time= 2018-09-28T13:04:29.067
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 15 , Time= 2018-09-28T13:04:29.067
--------------
cacheMilliseconds=10500
--------------
CurrentRunCacheReads=4
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 16 , Time= 2018-09-28T13:04:30.068
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 16 , Time= 2018-09-28T13:04:30.068
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 16 , Time= 2018-09-28T13:04:30.068
--------------
cacheMilliseconds=11000
--------------
CurrentRunCacheReads=5
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 17 , Time= 2018-09-28T13:04:31.068
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 17 , Time= 2018-09-28T13:04:31.068
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 17 , Time= 2018-09-28T13:04:31.068
--------------
cacheMilliseconds=11500
--------------
CurrentRunCacheReads=6
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 18 , Time= 2018-09-28T13:04:32.068
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 18 , Time= 2018-09-28T13:04:32.068
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 18 , Time= 2018-09-28T13:04:32.068
--------------
cacheMilliseconds=12000
--------------
CurrentRunCacheReads=7
Cached Collection<SystemSetting> Read .. size=3
cacheAsideSettings !! SystemSetting.Key=101, SystemSetting.Value = ValueOf14680*, i = 19 , Time= 2018-09-28T13:04:33.069
cacheAsideSettings !! SystemSetting.Key=102, SystemSetting.Value = ValueOf14680*, i = 19 , Time= 2018-09-28T13:04:33.069
cacheAsideSettings !! SystemSetting.Key=103, SystemSetting.Value = ValueOf14680*, i = 19 , Time= 2018-09-28T13:04:33.069
--------------
NewedUpCounter=4 /* this last one not accurate since its "bailing out */
1 ответ
Выражение создания анонимного класса new Cache2kBuilder<String, String>() {}
используется как "маркер супертипа" для представления параметризованного типа во время выполнения. Для этого они создают подкласс (обычно анонимный класс), который расширяет параметризованный тип, где аргументы типа - это конкретные типы, фиксированные (жестко запрограммированные) во время компиляции. Поскольку суперкласс класса является частью объявления класса, он хранится вместе с общей информацией в части объявления файла класса, и эта информация может быть получена во время выполнения посредством отражения.
Обратите внимание, что то, что можно извлечь из файла класса во время выполнения, это именно то, что было жестко запрограммировано во время компиляции. Вот почему new Cache2kBuilder<String, TEntity>() {}
не работает - что было жестко запрограммировано в исходном коде во время компиляции, так это наличие переменной типа TEntity
вместо конкретного класса.
Cache2k предоставляет другой способ создания Cache2kBuilder
если класс не может быть исправлен во время компиляции и будет известен только во время выполнения:
theCache = Cache2kBuilder.of(String.class, entityClass)
.name("myCache").eternal(true).build();
где entityClass
это Class<TEntity>
который является объектом класса класса сущности во время выполнения. Таким образом, вы должны будете также передать в Class
объект для сущности, а не просто Supplier
для этого.