Статьи

Несколько конфигураций кэша с кофеином и весенней загрузкой

Кэширование является ключом к производительности почти каждого приложения. Иногда требуется распределенное кэширование , но не всегда. Во многих случаях локальный кэш будет работать просто отлично, и нет необходимости в дополнительных затратах и ​​сложности распределенного кэша.

Таким образом, во многих приложениях, включая обычные Spring и Spring Boot, вы можете использовать @Cacheable для любого метода, и его результат будет кэшироваться, чтобы при следующем вызове метода возвращался кэшированный результат.

Spring имеет некоторые реализации менеджера кэша по умолчанию, но внешние библиотеки всегда лучше и более гибки, чем простые реализации. Например, Caffeine — это высокопроизводительная библиотека кеша Java . А Spring Boot поставляется с CaffeineCacheManager . Итак, в идеале, это все, что вам нужно — вы просто создаете компонент управления кэшем и у вас есть кэширование для ваших аннотированных методов @Cacheable .

Однако предоставленный менеджер кэша позволяет вам настроить только одну спецификацию кэша. Спецификации кэша включают время истечения, начальную емкость, максимальный размер и т. Д. Таким образом, все ваши кэши в этом менеджере кэша будут создаваться с одной спецификацией кэша. Менеджер кэша поддерживает список предопределенных кэшей, а также динамически создаваемых кэшей, но в обоих случаях используется одна спецификация кэша. И это редко полезно для производства. Как правило, со встроенными кеш-менеджерами нужно быть осторожным .

Есть несколько блогов , в которых рассказывается, как определять пользовательские кэши с помощью пользовательских спецификаций. Однако эти параметры не поддерживают динамический сценарий использования спецификации кэша по умолчанию, который поддерживает встроенный менеджер. В идеале вы должны иметь возможность использовать любое имя в @Cacheable и автоматически должен создаваться кеш с некоторыми спецификациями по умолчанию, но у вас также должна быть возможность переопределить это для определенных кешей.

Вот почему я решил использовать более простой подход, чем определение всех кэшей в коде, что обеспечивает большую гибкость. Он расширяет CaffeineCacheManager для обеспечения этой функциональности:

01
02
03
04
05
06
07
08
09
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
/**
 * Extending Caffeine cache manager to allow flexible per-cache configuration
 */
public class FlexibleCaffeineCacheManager extends CaffeineCacheManager implements InitializingBean {
    private Map<String, String> cacheSpecs = new HashMap<>();
 
    private Map<String, Caffeine<Object, Object>> builders = new HashMap<>();
 
    private CacheLoader cacheLoader;
 
    @Override
    public void afterPropertiesSet() throws Exception {
        for (Map.Entry<String, String> cacheSpecEntry : cacheSpecs.entrySet()) {
            builders.put(cacheSpecEntry.getKey(), Caffeine.from(cacheSpecEntry.getValue()));
        }
    }
 
    @Override
    @SuppressWarnings("unchecked")
    protected Cache<Object, Object> createNativeCaffeineCache(String name) {
        Caffeine<Object, Object> builder = builders.get(name);
        if (builder == null) {
            return super.createNativeCaffeineCache(name);
        }
 
        if (this.cacheLoader != null) {
            return builder.build(this.cacheLoader);
        } else {
            return builder.build();
        }
    }
 
    public Map<String, String> getCacheSpecs() {
        return cacheSpecs;
    }
 
    public void setCacheSpecs(Map<String, String> cacheSpecs) {
        this.cacheSpecs = cacheSpecs;
    }
 
    public void setCacheLoader(CacheLoader cacheLoader) {
        super.setCacheLoader(cacheLoader);
        this.cacheLoader = cacheLoader;
    }
}

Короче говоря, он создает один компоновщик кофеина для каждой спецификации и использует его вместо компоновщика по умолчанию, когда требуется новый кеш.

Тогда пример конфигурации XML будет выглядеть так:

1
2
3
4
5
6
7
8
<bean id="cacheManager" class="net.bozho.util.FlexibleCaffeineCacheManager">
    <property name="cacheSpecification" value="expireAfterWrite=10m"/>
    <property name="cacheSpecs">
        <map>
            <entry key="statistics" value="expireAfterWrite=1h"/>
       </map>
    </property>
</bean>

С настройкой Java это довольно просто — вы просто устанавливаете карту cacheSpecs .

Хотя Spring уже превратился в огромный фреймворк, который предоставляет всевозможные функции, он не отказался от принципов расширяемости.

Расширение встроенных каркасных классов — это то, что происходит довольно часто, и это должно быть в каждом наборе инструментов. Эти классы создаются с учетом расширения — вы заметите, что многие методы в CaffeineCacheManager protected . Поэтому мы должны использовать это всякий раз, когда это необходимо.

Опубликовано на Java Code Geeks с разрешения Божидара Божанова, партнера нашей программы JCG . См. Оригинальную статью здесь: несколько конфигураций кэша с кофеином и весенней загрузкой.

Мнения, высказанные участниками Java Code Geeks, являются их собственными.