欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot_Cache自定義使用SimpleCacheManager方式

 更新時間:2023年07月27日 10:59:55   作者:恐龍弟旺仔  
這篇文章主要介紹了SpringBoot_Cache自定義使用SimpleCacheManager方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

SpringBoot_Cache自定義使用SimpleCacheManager

在SpringBoot_Cache中,會默認使用SimpleCacheManager。

但是筆者遇到一個問題,就是當前項目中也引用了redis的maven依賴,導致Cache使用了JedisManager,筆者還是想使用默認的SimpleCacheManager

這個時候就需要我們手動生成SimpleCacheManager的bean,則Cache會強制使用該bean

關于SpringBoot_Cache的使用筆者就不再贅述,讀者可參考網(wǎng)絡文章。

解決方案

創(chuàng)建一個Config類,然后主動生成SimpleCacheManager,代碼如下

@Configuration
public class CacheManagerConfig {
	@Bean("cacheManager")
	// List<Cache>會主動搜索Cache的實現(xiàn)bean,并添加到caches中
	public SimpleCacheManager cacheManager(List<Cache> caches){
		SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
		simpleCacheManager.setCaches(caches);
		return simpleCacheManager;
	}
	@Bean("stockDetail")
	public ConcurrentMapCacheFactoryBean stockDetail(){
		ConcurrentMapCacheFactoryBean stockDetail = new ConcurrentMapCacheFactoryBean();
		// 如果用戶設置名稱為stockDetail的緩存,則需要添加這樣的一個bean
		stockDetail.setName("stockDetail");
		return stockDetail;
	}
	@Bean("detailMsg")
	public ConcurrentMapCacheFactoryBean detailMsg(){
		ConcurrentMapCacheFactoryBean stockDetail = new ConcurrentMapCacheFactoryBean();
		// 如果用戶設置名稱為detailMsg的緩存,則需要添加這樣的一個bean
		stockDetail.setName("detailMsg");
		return stockDetail;
	}
}

注意:如果讀者在使用@Cache的時候,需要多個不同命名的cache時,需添加多個ConcurrentMapCacheFactoryBean

spring cache自定義spring cacheManager和cache

緩存 可以提高訪問速度,對高性能、高并發(fā)有一定的治療效果。

緩存從存儲位置可以分為 JVM級別緩存,進程級別緩存。JVM級別緩存優(yōu)點:訪問速度最快;缺點:不能實現(xiàn)分布式緩存,因為每個節(jié)點都是一個單獨的JVM實例,所以各個節(jié)點的緩存不可見,會導致緩存不一致。進程級別緩存優(yōu)點:保證緩存一致性,因為進程級別的緩存 相當于一個緩存服務器,各個節(jié)點都去同一個緩存服務器取數(shù)據(jù),所以緩存一致性有保證。進程級別緩存缺點:IO消耗,相對慢于JVM級別緩存,但還是比數(shù)據(jù)庫查詢快。

Spring 對 cache 進行了抽象 并提供注解。但沒有具體實現(xiàn)緩存。類似于JDBC接口的意思。定義了規(guī)范,讓小面的廠商進行具體的實現(xiàn)。其中定義了兩個主要的接口:緩存管理器接口:CacheManager  緩存接口:Cache 

緩存管理器接口:CacheManager

接口很簡單 只有兩個方法:

public interface CacheManager {
	@Nullable
	Cache getCache(String name);
	Collection<String> getCacheNames();
}

Cache getCache(String name);

此方法可以定義根據(jù)緩存名稱獲取緩存,此方法可以實現(xiàn)二級緩存。

Collection<String> getCacheNames();

此方法獲取所有緩存名稱。

cacheManager是spring獲取cache的入口,所以你可以在getCache(String name) 方法中定義你的獲取cache的實現(xiàn)邏輯。

public class MyCacheManager implements CacheManager {
	private ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
	public MyCacheManager(String name, Cache cache) {
		this.caches.put(name, cache);
	}
	@Override
	public Cache getCache(String name) {
        //更加緩存名字獲取緩存
		Cache cache = this.caches.get(name);
		if (cache != null) {
			return cache;
		} else {
            //如果指定的緩存名字沒有找到 則新建一個ConcurrentMapCache 并保存在cachemanager中
			ConcurrentMapCache newCache = new ConcurrentMapCache(name);
			caches.put(name, newCache);
			return newCache;
		}
	}
	@Override
	public Collection<String> getCacheNames() {
		return this.caches.keySet();
	}
}

自定義緩存實現(xiàn)

spring只是定義了緩存 并實現(xiàn)了幾個常用的cache比如目前較為流行的緩存有conCurrentMapCache、ehcache、caffeine。

而redis的實現(xiàn)由redis廠商提供。

其中conCurrentMapCache由spring實現(xiàn),在spring-context包中。ehcache、caffeine的實現(xiàn)放在了spring-context-support包下。

rediscache實現(xiàn)在 spring-data-redis包下

定義好cacheManager后將其加入spring容器管理。下面貼出緩存在spring配置文件中的配置有些bean是在接下來講的內(nèi)容。

<bean id="cacheManager" class="com.app.utils.cache.MyCacheManager">
		<constructor-arg value="userCache" /> <!-- 緩存名稱 -->
		<constructor-arg ref="mapCaffeCache" /> <!-- 緩存實現(xiàn)類 -->
	</bean>
	<!-- 自定義緩存實現(xiàn) -->
	<bean id="mapCaffeCache" class="com.app.utils.cache.MapCaffeCache"></bean>
	<!-- 自定義緩存key實現(xiàn) -->
	<bean id="cacheKeyGenerator"
		class="com.app.utils.cache.CacheKeyGenerator"></bean>
	<!-- 自定義spring啟動加載bean時加載緩存 -->
	<bean id="cacheBeanPostProcessor"
		class="com.app.CacheBeanPostProcessor"></bean>

配置好bean后 在cache注解中 都會有cacheManager的指定 比如@cacheable注解 就有cacheManager的指定

@Cacheable(cacheManager = "cacheManager", key = "#i", value = "userCache", condition = "#i>7", unless = "#i>8")
public String getList(int i) {
	return "list server method :: "
		+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}

cache接口

public interface Cache {
	/**
	 * Return the cache name.
	 */
	String getName();
	/**
	 * Return the underlying native cache provider.
	 */
	Object getNativeCache();
	//獲取緩存的主要方法
	@Nullable
	ValueWrapper get(Object key);
	@Nullable
	<T> T get(Object key, @Nullable Class<T> type);
	@Nullable
	<T> T get(Object key, Callable<T> valueLoader);
	//添加緩存的主要方法
	void put(Object key, @Nullable Object value);
	@Nullable
	default ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
		ValueWrapper existingValue = get(key);
		if (existingValue == null) {
			put(key, value);
		}
		return existingValue;
	}
	void evict(Object key);
	default boolean evictIfPresent(Object key) {
		evict(key);
		return false;
	}
	void clear();
	default boolean invalidate() {
		clear();
		return false;
	}
	@FunctionalInterface
	interface ValueWrapper {
		@Nullable
		Object get();
	}
	@SuppressWarnings("serial")
	class ValueRetrievalException extends RuntimeException {
		@Nullable
		private final Object key;
		public ValueRetrievalException(@Nullable Object key, Callable<?> loader, Throwable ex) {
			super(String.format("Value for key '%s' could not be loaded using '%s'", key, loader), ex);
			this.key = key;
		}
		@Nullable
		public Object getKey() {
			return this.key;
		}
	}
}

cache的自定義實現(xiàn)類

public class MapCaffeCache implements Cache {
//	private ConcurrentMapCache mapCache = new ConcurrentMapCache("mapCache");
	private com.github.benmanes.caffeine.cache.@NonNull Cache<Object, Object> mapCache = Caffeine.newBuilder()
			.expireAfterWrite(5, TimeUnit.SECONDS).expireAfterAccess(5, TimeUnit.SECONDS).maximumSize(5).build();
	private com.github.benmanes.caffeine.cache.@NonNull Cache<Object, Object> caffeCache = Caffeine.newBuilder()
			.expireAfterWrite(1, TimeUnit.MINUTES).expireAfterAccess(1, TimeUnit.MINUTES).maximumSize(100).build();
	@Autowired
	private StringRedisTemplate redisTemplate;
	private String name = "userCache";
	@Override
	public String getName() {
		return this.name;
	}
	@Override
	public Object getNativeCache() {
		return this;
	}
	@Override
	public ValueWrapper get(Object key) {
		@Nullable
		Object ob = mapCache.getIfPresent(key);
		// 如果一級緩存有數(shù)據(jù) 直接返回 不觸發(fā)二級緩存
		if (ob != null) {
			System.out.println(String.format("Cache L1 (CaffeineCache) :: %s = %s", key, ob));
			SimpleValueWrapper valueWrapper = new SimpleValueWrapper(ob);
			return valueWrapper;
		}
		Object obj = caffeCache.getIfPresent(key);
		if (obj != null) {
			SimpleValueWrapper valueWrapper2 = new SimpleValueWrapper(obj);
			System.out.println(String.format("Cache L2 (CaffeineCache) :: %s = %s", key, obj));
			// 如果二級緩存有數(shù)據(jù) 則更新到一級緩存
			mapCache.put(key, obj);
			return valueWrapper2;
		}
		return null;
	}
	@Override
	public <T> T get(Object key, Class<T> type) {
		return (T) get(key).get();
	}
	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
		return (T) get(key).get();
	}
	@Override
	public void put(Object key, Object value) {
		mapCache.put(key, value);
		caffeCache.put(key, value);
		//當nginx搭建集群時 用redis 訂閱/發(fā)布 功能同步各項目點的緩存一致性
		redisTemplate.convertAndSend("ch1", key + ":>" + value);
	}
	@Override
	public void evict(Object key) {
		mapCache.asMap().remove(key);
		caffeCache.asMap().remove(key);
	}
	@Override
	public void clear() {
		mapCache.asMap().clear();
		caffeCache.asMap().clear();
	}
}

當cacheManager和cache實現(xiàn)完成后就是具體的cache注解使用了。主要有@Cacheable @Cacheput @CacheEvict @Caching @CacheConfig。主要講下@cacheable 其他注解設置都基本差不多。

@Cacheable用于獲取緩存數(shù)據(jù),如果緩存沒有命中則執(zhí)行被注解的方法 一般是執(zhí)行數(shù)據(jù)庫查詢,并剛數(shù)據(jù)庫查詢結(jié)果放入緩存中,cacheable緩存注解主要有一下設置:

@Cacheable(cacheManager = "cacheManager", key = "#i", value = "userCache", condition = "#i>7", unless = "#i>8")
  • cacheManager :設置緩存管理器 相當于數(shù)據(jù)庫中的庫名稱
  • value : 設置緩存名稱 相當于數(shù)據(jù)庫中的表
  • key:設置緩存鍵名稱 緩存是一個key value存儲方式 所以可以是查找用的
  • condition :設置滿足條件 true則緩存 false不緩存
  • unless:設置不緩存條件 true不緩存 false 緩存

key的設置規(guī)則 

  • key = " 'key-name' " 寫死一個key 即 key-name 就是key的名字。注意要用單引號
  • key="#id" 使用注解的方法中的參數(shù) id 的值作為key ,id 是方法參數(shù)列表的名字
  • key="cacheKeyGenerator" cacheKeyGenerator為spring容器管理的自定義key生成器

自定義key生成器

實現(xiàn)KeyGenerator接口就可以自定義一個key生成方法

public class CacheKeyGenerator implements KeyGenerator {
	@Override
	public Object generate(Object target, Method method, Object... params) {
		if (params.length == 0) {
			return "spring:cache:defaultKey";
		} else {
			return target.getClass().getSimpleName() + ":" + method.getName();
		}
	}
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • mybatis查詢結(jié)果返回至實體類的示例代碼

    mybatis查詢結(jié)果返回至實體類的示例代碼

    這篇文章主要介紹了mybatis查詢結(jié)果返回至實體類的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • springboot+vue項目從第一行代碼到上線部署全流程

    springboot+vue項目從第一行代碼到上線部署全流程

    本文詳細介紹了如何從零開始搭建一個基于Spring Boot和Vue.js的前后端分離項目,并涵蓋項目需求分析、技術(shù)選型、項目結(jié)構(gòu)設計、前后端交互、部署上線等全過程,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • java實現(xiàn)文件導入導出

    java實現(xiàn)文件導入導出

    這篇文章主要介紹了java實現(xiàn)文件導入導出的方法和具體示例代碼,非常的簡單實用,有需要的小伙伴可以參考下
    2016-04-04
  • java實現(xiàn)獲取用戶的MAC地址

    java實現(xiàn)獲取用戶的MAC地址

    本文給大家匯總介紹了下使用java實現(xiàn)獲取客戶端用戶的MAC地址的方法,當然最后一種更全面一些,有需要的小伙伴們可以根據(jù)需求自由選擇。
    2015-10-10
  • java中synchronized鎖的升級過程

    java中synchronized鎖的升級過程

    這篇文章主要介紹了java中synchronized鎖的升級過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java中ArrayList 、LinkList的區(qū)別分析

    java中ArrayList 、LinkList的區(qū)別分析

    java中ArrayList 、LinkList的區(qū)別分析,需要的朋友可以參考一下
    2013-05-05
  • java?并發(fā)線程個數(shù)的如何確定

    java?并發(fā)線程個數(shù)的如何確定

    這篇文章主要介紹了java?并發(fā)線程個數(shù)的如何確定,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java實現(xiàn)對對碰小游戲

    java實現(xiàn)對對碰小游戲

    這篇文章主要為大家詳細介紹了java實現(xiàn)對對碰小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • java中\(zhòng)t,\n,\r,\b,\f 的作用及說明

    java中\(zhòng)t,\n,\r,\b,\f 的作用及說明

    這篇文章主要介紹了java中\(zhòng)t,\n,\r,\b,\f 的作用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • java編程題之順時針打印矩陣

    java編程題之順時針打印矩陣

    這篇文章主要為大家詳細介紹了java編程題之順時針打印矩陣,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03

最新評論