1. 程式人生 > >Spring Cache快取介紹

Spring Cache快取介紹

Spring 3.1 引入了激動人心的基於註釋(annotation)的快取(cache)技術,它本質上不是一個具體的快取實現方案(例如 EHCache 或者 OSCache),而是一個對快取使用的抽象,通過在既有程式碼中新增少量它定義的各種 annotation,即能夠達到快取方法的返回物件的效果。
Spring 的快取技術還具備相當的靈活性,不僅能夠使用 SpEL(Spring Expression Language)來定義快取的 key 和各種 condition,還提供開箱即用的快取臨時儲存方案,也支援和主流的專業快取例如 EHCache 整合。
其特點總結如下:
1.通過少量的配置 annotation 註釋即可使得既有程式碼支援快取
2.支援開箱即用 Out-Of-The-Box,即不用安裝和部署額外第三方元件即可使用快取
3.支援 Spring Express Language,能使用物件的任何屬性或者方法來定義快取的 key 和 condition
4.支援 AspectJ,並通過其實現任何方法的快取支援
5.支援自定義 key 和自定義快取管理者,具有相當的靈活性和擴充套件性

一、基於註解的支援

Spring為我們提供了幾個註解來支援Spring Cache。其核心主要是@Cacheable、@CachePut 和@CacheEvict。使用@Cacheable標記的方法在執行後Spring Cache將快取其返回結果,@CachePut主要針對方法配置,能夠根據方法的請求引數對其結果進行快取,和 @Cacheable不同的是,它每次都會觸發真實方法的呼叫,而使用@CacheEvict標記的方法會在方法執行前或者執行後移除Spring Cache中的某些元素。
[email protected]
@Cacheable可以標記在一個方法上,也可以標記在一個類上。當標記在一個方法上時表示該方法是支援快取的,當標記在一個類上時則表示該類所有的方法都是支援快取的。對於一個支援快取的方法,Spring會在其被呼叫後將其返回值快取起來,以保證下次利用同樣的引數來執行該方法時可以直接從快取中獲取結果,而不需要再次執行該方法。Spring在快取方法的返回值時是以鍵值對進行快取的,值就是方法的返回結果,至於鍵的話,Spring又支援兩種策略,預設策略和自定義策略,需要注意的是當一個支援快取的方法在物件內部被呼叫時是不會觸發快取功能的。@Cacheable可以指定三個屬性,value、key和condition。
value:快取的名稱,在 spring 配置檔案中定義,必須指定至少一個。如@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}
key:快取的 key,可以為空,如果指定要按照 SpEL 表示式編寫,如果不指定,則預設按照方法的所有引數進行組合。如@Cacheable(value=”testcache”,key=”#userName”)
condition:快取的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行快取。如@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

注:除了上述使用方法引數作為key之外,Spring還為我們提供了一個root物件可以用來生成key。通過該root物件我們可以獲取到以下資訊。

屬性名稱

描述

示例

methodName

當前方法名

#root.methodName

method

當前方法

#root.method.name

target

當前被呼叫的物件

#root.target

targetClass

當前被呼叫的物件的class

#root.targetClass

args

當前方法引數組成的陣列

#root.args[0]

caches

當前被呼叫的方法使用的Cache

#root.caches[0].name

[email protected]
在支援Spring Cache的環境下,對於使用@Cacheable標註的方法,Spring在每次執行前都會檢查Cache中是否存在相同key的快取元素,如果存在就不再執行該方法,而是直接從快取中獲取結果進行返回,否則才會執行並將返回結果存入指定的快取中。@CachePut也可以宣告一個方法支援快取功能。與@Cacheable不同的是使用@CachePut標註的方法在執行前不會去檢查快取中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的快取中。
@CachePut也可以標註在類上和方法上。使用@CachePut時我們可以指定的屬性跟@Cacheable是一樣的。
[email protected]
@CacheEvict是用來標註在需要清除快取元素的方法或類上的。當標記在一個類上時表示其中所有的方法的執行都會觸發快取的清除操作。@CacheEvict可以指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語義與@Cacheable對應的屬性類似。即value表示清除操作是發生在哪些Cache上的(對應Cache的名稱);key表示需要清除的是哪個key,如未指定則會使用預設策略生成的key;condition表示清除操作發生的條件。下面我們來介紹一下新出現的兩個屬性allEntries和beforeInvocation。 
allEntries:是否清空所有快取內容,預設為 false,如果指定為 true,則方法呼叫後將立即清空所有快取。如:@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation:是否在方法執行前就清空,預設為 false,如果指定為 true,則在方法還沒有執行的時候就清空快取,預設情況下,如果方法執行丟擲異常,則不會清空快取。如:@CachEvict(value=”testcache”,beforeInvocation=true)
其他引數和@Cacheable相同
[email protected]
@Caching註解可以讓我們在一個方法或者類上同時指定多個Spring Cache相關的註解。其擁有三個屬性:cacheable、put和evict,分別用於指定@Cacheable、@CachePut和@CacheEvict。如: @Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),@CacheEvict(value = "cache3", allEntries = true) })

二、例項

使用map集合實現快取管理,演示spring cache的使用。

1.建立快取物件例項

package org.springframework.cache.demo;

import java.io.Serializable;

//快取物件
public class User implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int id; 
	private String name;
	
	public User(){
	}
	
	public User(String name){
		this.name= name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	} 
}
2.物件服務實現類
package org.springframework.cache.demo;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

/**
 * 業務服務
 * 
 */
public class UserService {

	@Cacheable(value = "userCache",key="#userName")
	// 使用了一個快取名叫 userCache
	public User getUserByName(String userName) {
		// 方法內部實現不考慮快取邏輯,直接實現業務
		return getFromDB(userName);
	}

	@CacheEvict(value = "userCache", key = "#user.name")
	// 清空 accountCache 快取
	public void updateUser(User user) {
		updateDB(user);
	}

	@CacheEvict(value = "userCache", allEntries = true,beforeInvocation=true)
	// 清空 accountCache 快取
	public void reload() {
	}

	private User getFromDB(String userName) {
		System.out.println("查詢資料庫..." + userName);
		return new User(userName);
	}

	private void updateDB(User user) {
		System.out.println("更新資料庫資料..." + user.getName());
	}
}

3.快取實現

package org.springframework.cache.demo.mycache;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

public class MyCache implements Cache {

	private String name;
	private Map<String, Object> store = new ConcurrentHashMap<String, Object>();;

	public MyCache() {
	}

	public MyCache(String name) {
		this.name = name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void clear() {
		store.clear();
	}

	public void evict(Object obj) {
	}

	public ValueWrapper get(Object key) {
		ValueWrapper result = null;
		Object thevalue = store.get(key);
		if (thevalue != null) {
			result = new SimpleValueWrapper(thevalue);
		}
		return result;
	}

	public <T> T get(Object key, Class<T> clazz) {
		return clazz.cast(store.get(key));
	}

	public String getName() {
		return name;
	}

	public Object getNativeCache() {
		return store;
	}

	public void put(Object key, Object value) {
		store.put((String) key, value);
	}

	public ValueWrapper putIfAbsent(Object key, Object value) {
		put(key, value);
		return new SimpleValueWrapper(value);
	}
}
4.spring配置
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
	<!-- 啟用快取註解功能,這個是必須的,否則註解不會生效,另外,該註解一定要宣告在spring主配置檔案中才會生效 -->
	<cache:annotation-driven cache-manager="cacheManager" />

	<bean id="userService" class="org.springframework.cache.demo.UserService" />

	<!-- generic cache manager -->
	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean class="org.springframework.cache.demo.mycache.MyCache"
					p:name="userCache" />
			</set>
		</property>
	</bean>
</beans>
5.執行類
package org.springframework.cache.demo.mycache;

import org.springframework.cache.demo.User;
import org.springframework.cache.demo.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyMain {

	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-cache-mycache.xml");
		UserService userService = context.getBean(UserService.class);
		// 第一次查詢,應該走資料庫
		System.out.print("第一次查詢...");
		userService.getUserByName("hello");
		// 第二次查詢,應該不查資料庫,直接返回快取的值
		System.out.println("第二次查詢...");
		userService.getUserByName("hello");
		System.out.println();
		System.out.println("==============");

		// 更新某個記錄的快取,首先構造兩個使用者記錄,然後記錄到快取中
		User user1 = userService.getUserByName("user1");
		// 開始更新其中一個
		user1.setId(1000);
		userService.updateUser(user1);
		// 因為被更新了,所以會查詢資料庫
		userService.getUserByName("user1");
		// 再次查詢,應該走快取
		userService.getUserByName("user1");
		// 更新所有快取
		userService.reload();
		System.out.println("清楚所有快取");
		// 查詢資料庫
		userService.getUserByName("user1");
		userService.getUserByName("user2");
		// 查詢快取
		userService.getUserByName("user1");
		userService.getUserByName("user2");
	}
}
執行結果:
第一次查詢...查詢資料庫...hello
第二次查詢...

==============
查詢資料庫...user1
更新資料庫資料...user1
清楚所有快取
查詢資料庫...user1
查詢資料庫...user2

相關推薦

Spring cache資料(三。註釋驅動的 Spring cache 快取介紹

概述 Spring 3.1 引入了激動人心的基於註釋(annotation)的快取(cache)技術,它本質上不是一個具體的快取實現方案(例如 EHCache 或者 OSCache),而是一個對快取使用的抽象,通過在既有程式碼中新增少量它定義的各種 annotation,即能夠達到快取

Spring Cache快取介紹

Spring 3.1 引入了激動人心的基於註釋(annotation)的快取(cache)技術,它本質上不是一個具體的快取實現方案(例如 EHCache 或者 OSCache),而是一個對快取使用的抽象,通過在既有程式碼中新增少量它定義的各種 annotation,即能夠達

spring cache快取配置

本文介紹如何在springboot中使用預設的spring cache,宣告式快取Spring 定義 CacheManager 和 Cache 介面用來統一不同的快取技術。例如 JCache、 EhCache、 Hazelcast、 Guava、 Redis 等。在使用 Sp

Spring Cache快取註解

[TOC] # Spring Cache快取註解 > 本篇文章程式碼示例在[Spring Cache簡單實現](baidu.com)上的程式碼示例加以修改。 ==只有使用public定義的方法才可以被快取,而private方法、protected 方法或者使用default 修飾符的方法都不能被快

淺談快取-註解驅動的快取 Spring cache介紹

在我們平常的工作當中,有好多場景需要用到快取技術,如redis,ehcache等來加速資料的訪問。作為淺談快取的第一篇筆者不想談論具體的快取技術,我更想介紹一下Spring中每次閱讀都會使我心中泛起波瀾的一個東西,那就是基於註解的快取技術。我們先看Spring參考文件中的一句

快取篇(三)- Spring Cache框架

前兩篇我們講了Guava和JetCache,他們都是快取的具體實現,今天給大家分析一下Spring框架本身對這些快取具體實現的支援和融合,使用Spring Cache將大大的減少我們的Spring專案中快取使用的複雜度,提高程式碼可讀性。本文將從以下幾個方面來認識Spring Cache框架 背

SPRING CACHE REDIS 註解式實現快取策略

為了解決資料庫查詢效率瓶頸,提升併發系統能力,快取的應用已經非常普遍和必要了。剛接觸REDIS時,如何使SPRING框架與REDIS更高效地整合,困擾了我很長時間。 先說下不使用SPRING CACHE時的兩種快取應用模式: 1.使用redis作為持久層的二級快

Spring Boot 菜鳥教程 17 Cache-快取

GitHub 快取 快取就是資料交換的緩衝區(稱作Cache),當某一硬體要讀取資料時,會首先從快取中查詢需要的資料,如果找到了則直接執行,找不到的話則從記憶體中找。由於快取的執行速度比記憶體快得多,故快取的作用就是幫助硬體更快地執行。 因為快取往

java中利用spring cache解耦業務中的快取

雖然以前實現快取的方式,是定義了快取操作介面,可以靈活實現不同的快取,可畢竟精力有限,要完成不同的快取實現也是件麻煩的事。更要命的是,業務程式碼中有大量快取操作的程式碼,耦合度太高,看著很不優雅。 所以呢,抽空了解了一下其它實現方案。這不,spring3.1開始,支援基於註解的快取,算是目前我比較可以接

使用Spring Cache + Redis + Jackson Serializer快取資料庫查詢結果中序列化問題的解決

應用場景 我們希望通過快取來減少對關係型資料庫的查詢次數,減輕資料庫壓力。在執行DAO類的select***(), query***()方法時,先從Redis中查詢有沒有快取資料,如果有則直接從Redis拿到結果,如果沒有再向資料庫發起查詢請求取資料。

《partner4java 講述Spring入門》之:spring cache支援(spring3.1如何使用cache 快取

(以下內容參照自官方文件;p4jorm下載地址http://blog.csdn.net/partner4java/article/details/8629578;cache demo下載地址http://download.csdn.net/detail/partner4ja

Spring Cache快取註解使用

前言SpringCache是SpringFramework3.1引入的新特性,提供了基於註解的快取配置方法.SpringCache是SpringFramework3.1引入的新特性,提供了基於註解的快取配置方法pom檔案引入<dependency> <gr

Spring Cache緩存技術的介紹

jpg 可能 主動 .html org wire 文件內容 boolean 核心 緩存用於提升系統的性能,特別適用於一些對資源需求比較高的操作。本文介紹如何基於spring boot cache技術,使用caffeine作為具體的緩存實現,對操作的結果進行緩存。 demo場

Spring Cache擴充套件為例介紹如何進行高效的原始碼的閱讀

摘要 日常開發中,需要用到各種各樣的框架來實現API、系統的構建。作為程式設計師,除了會使用框架還必須要了解框架工作的原理。這樣可以便於我們排查問題,和自定義的擴充套件。那麼如何去學習框架呢。通常我們通過閱讀文件、檢視原始碼,然後又很快忘記。始終不能融匯貫通。本文主要基於Spring Cache擴充套件為例,

快取抽象層Spring cache實戰操作

Spring快取抽象 Spring從3.1開始定義了一系列抽象介面來統一不同的快取技術;並支援使用JCache(JSR-107)註

一個快取使用的思考:Spring Cache VS Caffeine 原生 API

最近在學習本地快取發現,在 Spring 技術棧的開發中,既可以使用 Spring Cache 的註解形式操作快取,也可用各種快取方案的原生 API。那麼是否 Spring 官方提供的就是最合適的方案呢?那麼本文將通過一個案例來為你揭曉。 Spring Cache Since version 3.1, th

【開源專案系列】如何基於 Spring Cache 實現多級快取(同時整合本地快取 Ehcache 和分散式快取 Redis)

## 一、快取 當系統的併發量上來了,如果我們頻繁地去訪問資料庫,那麼會使資料庫的壓力不斷增大,在高峰時甚至可以出現數據庫崩潰的現象。所以一般我們會使用快取來解決這個資料庫併發訪問問題,使用者訪問進來,會先從快取裡查詢,如果存在則返回,如果不存在再從資料庫裡查詢,最後新增到快取裡,然後返回給使用者,當然了,接

spring註解使用介紹

print sqlite 測試 www oca oid pat 不知道 text 註解註入顧名思義就是通過註解來實現註入,Spring和註入相關的常見註解有Autowired、Resource、Qualifier、Service、Controller、Repository、

Spring-SpringJdbcTemlate配置介紹

ger ng- 2.x find pro basename local ann clas 使用spring的jdbcTemplate進一步操作JDBC 一、普通配置 SpringJdbcTemplate連接數據庫並操作數據 1.applicationContext.x

dubbo&hsf&spring-cloud簡單介紹

服務器端 場景 hessian 發展 分布式系 梳理 擴展點 中心 筆記本 Dubbo: 簡介:Dubbo是一個分布式服務框架,以及SOA治理方案。其功能主要包括:高性能NIO通訊及多協議集成,服務動態尋址與路由,軟負載均衡與容錯,依賴分析與降級等。 底部NIO基於nett