Vodič za keširanje u proljeće

1. Apstrakcija predmemorije?

U ovom ćemo članku pokazati kako to učiniti upotrijebite apstrakciju keširanja u proljeće - i općenito, poboljšajte performanse vašeg sustava.

Omogućit ćemo jednostavno predmemoriranje za neke primjere stvarnih metoda i razgovarat ćemo o tome kako praktično možemo poboljšati izvedbu tih poziva pametnim upravljanjem predmemorijom.

2. Početak rada

Apstrakcija predmemoriranja jezgre koju pruža Spring nalazi se u proljeće-kontekst modul. Dakle, kada koristimo Maven, naš pom.xml treba sadržavati sljedeću ovisnost:

 org.springframework proljeće-kontekst 5.2.8.OSLOBOĐENJE 

Zanimljivo je da postoji još jedan modul s imenom proljeće-kontekst-podrška, koji sjedi na vrhu proljeće-kontekst modul i pruža još nekoliko CacheManagers potpomognuti poput EhCachea ili kofeina. Ako ćete ih koristiti kao predmemoriju, tada upotrijebite proljeće-kontekst-podrška umjesto toga modul:

 org.springframework proljeće-kontekst-podrška 5.2.8.OSLOBOĐENJE 

Budući da je proljeće-kontekst-podrška modul tranzitivno ovisi o proljeće-kontekst za modul, nema potrebe za zasebnom deklaracijom ovisnosti za proljeće-kontekst.

2.1. Proljetni čizme

Ako ste korisnik Spring Boota, upotrijebite predmemorija boot-starter-cache početni paket za jednostavno dodavanje ovisnosti o predmemoriranju:

 org.springframework.boot spring-boot-starter-cache 2.3.3.OSLOBODI 

Ispod poklopca motora starter donosi proljeće-kontekst-podrška modul.

3. Omogućite keširanje

Da bi omogućio predmemoriranje, Spring dobro koristi napomene, slično kao što omogućuje bilo koju drugu značajku na razini konfiguracije u okviru.

Značajka predmemoriranja može se deklarativno omogućiti jednostavnim dodavanjem @EnableCaching napomena za bilo koju od klasa konfiguracije:

@Configuration @EnableCaching javna klasa CachingConfig {@Bean public CacheManager cacheManager () {return new ConcurrentMapCacheManager ("adrese"); }}

Možete, naravno, omogućiti upravljanje predmemorijom s XML-om konfiguracija također:

Bilješka: Nakon što omogućimo predmemoriranje - za minimalno postavljanje - moramo registrirati a cacheManager.

3.1. Korištenje Spring Boota

Kada koristite Spring Boot, puka prisutnost početnog paketa na stazi pored EnableCaching anotacija bi registrirala isto ConcurrentMapCacheManager. Dakle, nema potrebe za zasebnom deklaracijom graha.

Također, možemo prilagoditi automatski konfiguriranu CacheManager koristeći jedan ili više CacheManagerCustomizer grah:

@Component javna klasa SimpleCacheCustomizer implementira CacheManagerCustomizer {@Override custom void customize (ConcurrentMapCacheManager cacheManager) {cacheManager.setCacheNames (asList ("korisnici", "transakcije")); }}

The CacheAutoConfiguration automatska konfiguracija uzima ove prilagodnike i primjenjuje ih na trenutne CacheManager prije njegove potpune inicijalizacije.

4. Koristite predmemoriranje s bilješkama

Nakon što omogućimo predmemoriranje, sljedeći je korak vezivanje ponašanja predmemoriranja za metode s deklarativnim bilješkama.

4.1. @Mogućnost predmemoriranja

Najjednostavniji način omogućavanja ponašanja u predmemoriji metode je razgraničenje @Cacheable i parameterizirajte ga imenom predmemorije u koju će se pohraniti rezultati:

@Cacheable ("adrese") javni niz getAddress (kupac) {...} 

The getAddress () poziv prvo će provjeriti predmemoriju adrese prije nego što zapravo započne metodu, a zatim predmemorira rezultat.

Iako je u većini slučajeva dovoljna jedna predmemorija, Spring okvir također podržava više predmemorija koje se prosljeđuju kao parametri:

@Cacheable ({"adrese", "direktorij"}) javni niz getAddress (kupac kupca) {...}

U ovom slučaju, ako bilo koja od predmemorija sadrži traženi rezultat, rezultat se vraća i metoda se ne poziva.

4.2. @CacheEvict

Sad, što bi bio problem s izradom svih metoda @Cacheable?

Problem je u veličini - ne želimo popuniti predmemoriju vrijednostima koje nam nisu često potrebne. Predmemorije mogu narasti prilično velike, prilično brzo, a mi bismo mogli zadržati puno zastarjelih ili neiskorištenih podataka.

The @CacheEvict napomena se koristi za označavanje uklanjanja jedne ili više / svih vrijednosti - tako da se nove vrijednosti mogu ponovno učitati u predmemoriju:

@CacheEvict (value = "adrese", allEntries = true) javni niz getAddress (kupac kupca) {...}

Ovdje koristimo dodatni parametar allEntries zajedno s predmemorijom koju treba isprazniti - za brisanje svih unosa u predmemoriju adrese i pripremite ga za nove podatke.

4.3. @CachePut

Dok @CacheEvict smanjuje općenite troškove pretraživanja unosa u velikoj predmemoriji uklanjanjem ustajalih i neiskorištenih unosa, idealno bi bilo da želite izbjegavajte izbacivanje previše podataka iz predmemorije.

Umjesto toga, željeli biste selektivno i inteligentno ažurirati unose kad god se promijene.

Uz @CachePut napomena, možete ažurirati sadržaj predmemorije bez ometanja izvršavanja metode. Odnosno, metoda bi se uvijek izvršavala, a rezultat keširao.

@CachePut (value = "adrese") javni niz getAddress (kupac kupca) {...}

Razlika između @Cacheable i @CachePut je li to @Cacheable htjeti preskočite izvođenje metode, dok @CachePut htjeti zapravo pokrenuti metodu a zatim stavi svoje rezultate u predmemoriju.

4.4. @Predmemoriranje

Što ako želite koristiti više napomena iste vrste za predmemoriranje metode. Pogledajte netočan primjer u nastavku:

@CacheEvict ("adrese") @CacheEvict (vrijednost = "direktorij", ključ = kupac.ime) javni niz getAddress (kupac kupca) {...}

Gornji kôd ne bi uspio prevesti jer Java ne dopušta deklariranje više bilješki istog tipa za datu metodu.

Zaobilazno rješenje gornjeg problema bilo bi:

@Caching (evict = {@CacheEvict ("adrese"), @CacheEvict (value = "directory", key = "# customer.name")}) javni niz getAddress (kupac kupca) {...}

Kao što je prikazano u isječku koda gore, možete grupiraj više bilješki predmemoriranja s @Cachingi upotrijebite ga za implementaciju vlastite prilagođene logike predmemoriranja.

4.5. @CacheConfig

Uz @CacheConfig napomena, možete pojednostaviti neke konfiguracije predmemorije na jedno mjesto - na razini klase - tako da ne morate deklarirati stvari više puta:

@CacheConfig (cacheNames = {"adrese"}) javna klasa CustomerDataService {@Cacheable javni niz getAddress (kupac kupca) {...}

5. Uvjetno keširanje

Ponekad predmemoriranje možda neće dobro funkcionirati za metodu u svim situacijama.

Na primjer - ponovna upotreba našeg primjera iz @CachePut napomena - ovo će izvršiti metodu, kao i predmemorirati rezultate svaki put:

@CachePut (value = "adrese") javni niz getAddress (kupac kupca) {...} 

5.1. Parametar stanja

Sada - ako želimo veću kontrolu nad aktivnošću bilješke - @CachePut može se parametarizirati s parametrom stanja koji uzima SpEL izraz kako bi se osiguralo da se rezultati keširaju na temelju procjene tog izraza:

@CachePut (value = "adrese", uvjet = "# customer.name == 'Tom'") javni niz getAddress (kupac kupca) {...}

5.2. Osim parametra

Također možemo kontrolirati predmemoriranje na temelju rezultata metode, a ne ulaznih podataka - putem osim ako parametar:

@CachePut (value = "adrese", osim ako je = "# result.length () <64") javni niz getAddress (kupac kupca) {...}

Gornja napomena će predmemorirati adrese osim ako nisu kraće od 64 znaka.

Važno je znati da stanje i osim ako parametri se mogu koristiti zajedno sa svim bilješkama predmemoriranja.

Ovakva vrsta uvjetnog predmemoriranja može se pokazati vrlo korisnom za upravljanje velikim rezultatima i prilagođavanje ponašanja na temelju ulaznih parametara, umjesto nametanja generičkog ponašanja za sve operacije.

6. Deklarativno predmemoriranje na temelju XML-a

U slučaju da nemate pristup izvornom kodu svoje aplikacije ili želite vanjski ubrizgati ponašanje predmemoriranja, također možete koristiti deklarativno predmemoriranje na temelju XML-a.

Evo naše XML konfiguracije:

7. Keširanje zasnovano na Javi

I evo ekvivalentne Java konfiguracije:

@Configuration @EnableCaching javna klasa CachingConfig {@Bean public CacheManager cacheManager () {SimpleCacheManager cacheManager = new SimpleCacheManager (); cacheManager.setCaches (Arrays.asList (novi ConcurrentMapCache ("direktorij"), novi ConcurrentMapCache ("adrese"))); vratiti cacheManager; }}

I ovdje je naš CustomerDataService:

@Component javna klasa CustomerDataService {@Cacheable (value = "adrese", key = "# customer.name") javni niz getAddress (kupac kupac) {return customer.getAddress (); }}

8. Sažetak

U ovom smo članku raspravljali o osnovama keširanja u proljeće i kako dobro upotrijebiti tu apstrakciju s napomenama.

Potpuna provedba ovog članka može se naći u projektu GitHub.