App下載

使用 Caffeine 和 Spring Boot 的多個(gè)緩存配置

伸手挽明月 2021-09-24 10:12:14 瀏覽數(shù) (3784)
反饋

緩存是幾乎所有應(yīng)用程序性能的關(guān)鍵。有時(shí)需要分布式緩存,但并非總是如此。在許多情況下,本地緩存可以正常工作,并且不需要分布式緩存的開銷和復(fù)雜性。

因此,在許多應(yīng)用程序中,包括普通的 Spring 和 Spring Boot,您可以在任何方法上使用?@Cacheable?,其結(jié)果將被緩存,以便下次調(diào)用該方法時(shí),返回緩存的結(jié)果。

Spring 有一些默認(rèn)的緩存管理器實(shí)現(xiàn),但外部庫總是比簡單的實(shí)現(xiàn)更好、更靈活。例如,Caffeine 是一個(gè)高性能的 Java 緩存庫。Spring Boot 帶有一個(gè)?CaffeineCacheManager?. 因此,理想情況下,您只需創(chuàng)建一個(gè)緩存管理器 bean 并為您的帶有?@Cacheable?注釋的方法緩存。

但是,提供的緩存管理器允許您僅配置一種緩存規(guī)范。緩存規(guī)范包括到期時(shí)間、初始容量、最大大小等。因此,此緩存管理器下的所有緩存都將使用單個(gè)緩存規(guī)范創(chuàng)建。緩存管理器支持預(yù)定義緩存列表以及動(dòng)態(tài)創(chuàng)建的緩存,但在這兩種情況下都使用單個(gè)緩存規(guī)范。這對生產(chǎn)很少有用。作為一般規(guī)則,您必須小心使用內(nèi)置緩存管理器。

這篇文章告訴您如何使用自定義規(guī)范定義自定義緩存。但是,這些選項(xiàng)不支持內(nèi)置管理器支持的動(dòng)態(tài)默認(rèn)緩存規(guī)范用例。理想情況下,您應(yīng)該能夠使用任何名稱?@Cacheable?并自動(dòng)使用某些默認(rèn)規(guī)范創(chuàng)建緩存,但您還應(yīng)該可以選擇覆蓋特定緩存的名稱。

這就是為什么我決定使用比在代碼中定義所有緩存更簡單的方法,以提供更大的靈活性。它擴(kuò)展了?CaffeineCacheManager?提供該功能:

/**
 * Extending Caffeine cache manager to allow flexible per-cache configuration
 */
public class FlexibleCaffeineCacheManagerextends CaffeineCacheManagerimplements 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;
    }
}

簡而言之,它為每個(gè)規(guī)范創(chuàng)建一個(gè)咖啡因構(gòu)建器,并在需要新緩存時(shí)使用它而不是默認(rèn)構(gòu)建器。

然后示例 XML 配置將如下所示:

<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 配置非常簡單——您只需設(shè)置?cacheSpecs?映射。

雖然 Spring 已經(jīng)變成了一個(gè)提供各種功能的龐大框架,但它并沒有放棄可擴(kuò)展性的設(shè)計(jì)原則。

擴(kuò)展內(nèi)置框架類是經(jīng)常發(fā)生的事情,它應(yīng)該在每個(gè)人的工具箱中。這些類是在考慮擴(kuò)展的情況下創(chuàng)建的 - 您會注意到?CaffeineCacheManagerare?中的許多?protected?方法。所以我們應(yīng)該在需要的時(shí)候利用它。


0 人點(diǎn)贊