日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

Spring 之 @Cacheable 緩存使用教程

作者:浪子塵晨 更新時間: 2023-12-25 編程語言

1、@Cacheable 指定使用緩存

定義個 Controller ,在方法上加上注解?@Cacheable,配置要使用哪些緩存,比如 myMapCache 表示一級緩存是 Map,myRedisCache 表示二級緩存是 Redis。并配置緩存 key。 key 由 SPEL 表達式組成,Spring 可以動態(tài)解析生成緩存 key。

提示:myMapCache、myRedisCache 均為注入 Spring 緩存的名稱

@RestController
public class CachingAnnoController {

	@Cacheable(cacheNames = {"myMapCache","myRedisCache"},key = "'test_'+#key")
	@RequestMapping("/cachingAnno")
	public String cachingAnno(String key,String value){
		System.out.println("查詢數(shù)據(jù)庫值 = " + value);
		return "value";
	}
}

2、@EnableCaching 開啟緩存功能

用過 @Cacheable 注解的都知道,要開啟緩存功能必須通過 @EnableCaching 注解。代碼如下:

@ComponentScan(value = "com.gwm")
@Configuration
@EnableCaching
public class SpringConfig {

}

3、引入具體要使用的緩存—實現(xiàn) Cache 接口

上述 @EnableCaching、@Cacheable 都是 Spring 提供的基本緩存框架,而具體的緩存需要自己引入。比如現(xiàn)在自己定義兩個緩存:MyMapCache 類 、MyRedisCache 類。然后實現(xiàn)接口方法。

Spring 提供 Cache 作為標準化接口,具體的實現(xiàn) Spring 不管,你自己去實現(xiàn)。但是 Spring 也是有幾個默認實現(xiàn)的,比如:CaffeineCache、EhCacheCache、ConcurrentMapCache、JCacheCache 等。

public class MyMapCache implements Cache {

	public static final Map<Object, Object> map = new ConcurrentHashMap<>();

	private String cacheName;

	public MyMapCache(String cacheName) {
		this.cacheName = cacheName;
	}

	@Override
	public String getName() {
		return cacheName;
	}

	@Override
	public Object getNativeCache() {
		return null;
	}

	@Override
	public ValueWrapper get(Object key) {
		System.out.println(">>>>>>我是 MyMapCache 緩存中的 get() 方法");
		Object o = map.get(key);
		if (Objects.nonNull(o)) {
			return new SimpleValueWrapper(o);
		}
		return null;
	}

	@Override
	public <T> T get(Object key, Class<T> type) {

		return (T)map.get(key);
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
		return (T)map.get(key);
	}

	@Override
	public void put(Object key, Object value) {
		System.out.println(">>>>>>我是 MyMapCache 緩存中的 put() 方法");
		map.put(key, value);
	}

	@Override
	public void evict(Object key) {
		map.remove(key);
	}

	@Override
	public void clear() {
		map.clear();
	}
}

MyRedisCache 類實現(xiàn),代碼如下:

public class MyRedisCache implements Cache {

	private String cacheName;
	private RedisTemplate<Object,Object> redisTemplate;

	public MyRedisCache(String cacheName, RedisTemplate<Object, Object> redisTemplate) {
		this.cacheName = cacheName;
		this.redisTemplate = redisTemplate;
	}

	@Override
	public String getName() {
		return cacheName;
	}

	@Override
	public Object getNativeCache() {
		return this;
	}

	@Override
	public ValueWrapper get(Object key) {
		System.out.println(">>>>>>我是 MyRedisCache 緩存中的 get() 方法");
		Object o = redisTemplate.opsForValue().get(key);
		if (Objects.nonNull(o)) {
			return new SimpleValueWrapper(o);
		}

		return null;
	}

	@Override
	public <T> T get(Object key, Class<T> type) {
		return null;
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
		return null;
	}

	@Override
	public void put(Object key, Object value) {
		System.out.println(">>>>>>我是 MyRedisCache 緩存中的 put() 方法");
		redisTemplate.opsForValue().set(key,value);
		redisTemplate.expire(key, Duration.ofMillis(3000));
	}

	@Override
	public void evict(Object key) {
		redisTemplate.delete(key);
	}

	@Override
	public void clear() {
		redisTemplate.execute((RedisCallback<Object>) conn->{

			// 清空所有緩存數(shù)據(jù),要格外注意這個操作,很危險
			conn.flushDb();

			return ">>>>>>flush db success!";
		});
	}
}

4、緩存管理類—實現(xiàn) CacheManager 接口

自定義緩存定義完之后,光擺在這里肯定是不能起作用的,還需要借助 Spring 標準化接口 CacheManager 類來把緩存加入到緩存切面邏輯中。

比如實現(xiàn) MyMapCache 緩存管理類 MyMapCacheManager,代碼如下:

public class MyMapCacheManager implements CacheManager {

	@Override
	public Cache getCache(String name) {
		return new MyMapCache(name);
	}

	@Override
	public Collection<String> getCacheNames() {
		return Arrays.asList("myMapCache");
	}
}

實現(xiàn) MyRedisCache 緩存管理類 MyRedisCacheManager,代碼如下:

public class MyRedisCacheManager implements CacheManager {

	@Override
	public Cache getCache(String name) {
		return new MyRedisCache(name,redisTemplate);
	}

	@Override
	public Collection<String> getCacheNames() {
		return Arrays.asList("myRedisCache");
	}
}

然后在配置入口類中通過 @Bean 引用具體的緩存。代碼如下:

@Configuration
public class MyRedisMainConfig {

	@Resource
	private RedisTemplate<Object,Object> redisTemplate;

	@Bean
	public MyMapCache myMapCache() {
		MyMapCache myMapCache = new MyMapCache("myMapCache");
		return myMapCache;
	}
	
	@Bean
	public MyRedisCache myRedisCache() {
		MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);

		return myRedisCache;
	}
	
	@Bean
	public MyRedisCacheManager cacheManager() {
		MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
		return redisCacheManager;
	}
	
	// @Bean 
	public MyMapCacheManager cacheManager() {
		MyRedisCacheManager redisCacheManager = new MyRedisCacheManager();
		return redisCacheManager;
	}
	
}

但是發(fā)現(xiàn)使用具體的管理類引入緩存,只能引入對應的緩存。比如 MyRedisCacheManager 管理類就只能引入 MyRedisCache 緩存,不能引入 MyMapCache。所以這是個弊端。如果想要使用雙緩存,那怎么辦呢?

5、雙緩存使用—實現(xiàn) AbstractCacheManager 抽象類

該抽象類提供 loadCaches() 方法,可以獲取到所有 Cache 接口實現(xiàn)類。所以這里能夠獲取到所有緩存。那么肯定是可以使用雙緩存。比如 MySimpleCacheManager 類實現(xiàn),代碼如下:

public class MySimpleCacheManager extends AbstractCacheManager implements ApplicationContextAware {

	private static final List<Cache> list = new ArrayList<>();

	private ApplicationContext context;
	/**
	 * 直接實現(xiàn) AbstractCacheManager 抽象類的鉤子方法,該類已經(jīng)寫好模版方法
	 * 當執(zhí)行的時候,如果 MyGuavaCacheManager 管理類 @Bean 的話,就會勾到這個方法邏輯
	 * @return
	 */
	@Override
	protected Collection<? extends Cache> loadCaches() {
		return list;
	}

	@Override
	public void afterPropertiesSet() {
		Map<String, Cache> beansOfType = context.getBeansOfType(Cache.class);
		list.addAll(beansOfType.values());
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
		this.context = applicationContext;
	}
}

然后再配置入口類,代碼如下:

@Configuration
public class MyRedisMainConfig {

	@Resource
	private RedisTemplate<Object,Object> redisTemplate;

	@Bean
	public MyMapCache myMapCache() {
		MyMapCache myMapCache = new MyMapCache("myMapCache");
		return myMapCache;
	}
	
	@Bean
	public MyRedisCache myRedisCache() {
		MyRedisCache myRedisCache = new MyRedisCache("myRedisCache",redisTemplate);
		return myRedisCache;
	}
	
	@Bean
	public MySimpleCacheManager cacheManager(@Qualifier("myMapCache") MyMapCache myMapCache,
												 @Qualifier("myRedisCache") MyRedisCache myRedisCache,
												 @Qualifier("myGuavaCache") MyGuavaCache myGuavaCache) {
												 
		SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
		simpleCacheManager.setCaches(Arrays.asList(myMapCache,myRedisCache,myGuavaCache));
		return simpleCacheManager;
	}
}

最終通過注入一個緩存管理類 MySimpleCacheManager 就可以使用到三個緩存。美滋滋。最終要使用,就通過?@Cacheable(cacheNames = {“myMapCache”,“myRedisCache”},key = “‘test_’+#key”)?即可使用 myMapCache、myRedisCache 緩存。如果還需要使用 myGuavaCache,直接往數(shù)組中添加即可。

6、 RedisCacheManager 內置類

在使用 Redis 緩存時,Spring 早已對其包裝完成,只需要引入 spring-data-redis 包即可。我們不需要寫 MyRedisCacheManager 類,Spring 早就提供 RedisCacheManager 類管理 Redis 緩存 。所以你只需能夠連接好 Redis 。然后通過 @Bean 將?RedisCacheManager?類注入即可使用 Redis 緩存。

原文鏈接:https://blog.csdn.net/fygkchina/article/details/134725916

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新