springboot 緩存@EnableCaching實(shí)例
springboot 緩存@EnableCaching
很多時(shí)候系統(tǒng)的瓶頸都在一些比較復(fù)雜的IO操作,例如讀取數(shù)據(jù)庫(kù),如果一些比較穩(wěn)定的數(shù)據(jù),一般的解決方案就是用緩存。spring boot提供了比較簡(jiǎn)單的緩存方案。只要使用 @EnableCaching即可完成簡(jiǎn)單的緩存功能。
緩存的實(shí)現(xiàn)有多種實(shí)現(xiàn),ConcurentHashMapCache , GuavaCache, EnCacheCache等多種實(shí)現(xiàn),spring boot 有默認(rèn)的實(shí)現(xiàn)。本文不深入源碼解讀,首先用起來(lái)。
此處我們模擬要緩存的User
class User {
private Long id;
private String name;
// setter getter
}
然后我們業(yè)務(wù)對(duì)象:
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Component;
/**
* @author micro
* @date 2017年8月2日
* @description :
*/
@Component
@EnableCaching
public class UserDao {
private Map<Long, User> userMap;
@PostConstruct
public void init() {
//模擬數(shù)據(jù)庫(kù)
userMap = new HashMap<Long, User>();
userMap.put(1L, new User(1L,"micro1"));
userMap.put(2L, new User(2L, "micro2"));
}
@Cacheable("user") // 注解key屬性可以執(zhí)行緩存對(duì)象user(可以理解為一個(gè)map)的key
public User getUser(Long userId) {
System.out.println("查詢數(shù)據(jù)庫(kù):userId ->" + userId);
return userMap.get(userId);
}
@Cacheable(value = "nameCache", key = "#name")
public User getUserByName(Long userId, String name) {
System.out.println("查詢數(shù)據(jù)庫(kù):userId ->" + userId);
return userMap.get(userId);
}
@Cacheable("nameCache")
public User getUserByName(String name) {
System.out.println("查詢數(shù)據(jù)庫(kù):userName : " + name);
for (Long k : userMap.keySet()) {
if (userMap.get(k).equals(name)) {
return userMap.get(k);
}
}
return null;
}
@CachePut("user") // 與Cacheable區(qū)別就是Cacheable先看緩存如果有,直接緩存換回,CachePut則是每次都會(huì)調(diào)用并且把返回值放到緩存
public User getUser2(Long userId) {
System.out.println("查詢數(shù)據(jù)庫(kù):userId : " + userId);
return userMap.get(userId);
}
@CacheEvict("user")
public void removeFromCache(Long userId) {
return ;
}
}
然后我們編寫(xiě)啟動(dòng)類:
@SpringBootApplication
public class CacheTest implements CommandLineRunner {
@Autowired
private UserDao userDao;
public static void main(String[] args) {
new SpringApplication(CacheTest.class).run(args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("第一次查詢");
System.out.println(userDao.getUser(1L));
System.out.println("第二次查詢");
System.out.println(userDao.getUser(1L));
userDao.removeFromCache(1L);// 移除緩存
System.out.println("第三次查詢");
userDao.getUser(1L);// 沒(méi)有緩存了
System.out.println("--------");
// 測(cè)試不同的key緩存
userDao.getUserByName("micro1");
userDao.getUserByName(1L, "micro1");// 指定了參數(shù)name 為key 此次讀取緩存
}
}
打印結(jié)果:
第一次查詢
查詢數(shù)據(jù)庫(kù):userId ->1
User@65da01f4
第二次查詢
User@65da01f4
第三次查詢
查詢數(shù)據(jù)庫(kù):userId ->1
--------
查詢數(shù)據(jù)庫(kù):userName : micro1
Spring @EnableCaching的工作原理
1、開(kāi)發(fā)人員使用注解@EnableCaching
2、注解@EnableCaching導(dǎo)入CachingConfigurationSelector
3、CachingConfigurationSelector根據(jù)注解@EnableCaching 屬性AdviceMode mode決定引入哪些配置類
PROXY: AutoProxyRegistrar,ProxyCachingConfiguration;ASPECTJ: AspectJCachingConfiguration;
本文以mode=PROXY為例;
4、CachingConfigurationSelector導(dǎo)入AutoProxyRegistrar會(huì)確保容器中存在一個(gè)自動(dòng)代理創(chuàng)建器(APC);
- 用于確保目標(biāo)bean需要被代理時(shí)有可用的代理創(chuàng)建器
5、ProxyCachingConfiguration向容器定義如下基礎(chǔ)設(shè)施bean
- 名稱為org.springframework.cache.config.internalCacheAdvisor類型為BeanFactoryCacheOperationSourceAdvisor的bean
- 名稱為cacheOperationSource類型為CacheOperationSource的bean
用于獲取方法調(diào)用時(shí)最終應(yīng)用的Spring Cache注解的元數(shù)據(jù)
- 名稱為cacheInterceptor類型為CacheInterceptor的bean
一個(gè)MethodInterceptor,包裹在目標(biāo)bean外面用于操作Cache的AOP Advice。
6、AutoProxyRegistrar在容器啟動(dòng)階段對(duì)每個(gè)bean創(chuàng)建進(jìn)行處理,如果該bean中有方法應(yīng)用了Spring Cache注解,為其創(chuàng)建相應(yīng)的代理對(duì)象,包裹上面定義的BeanFactoryCacheOperationSourceAdvisor bean;
7、使用了Spring Cache注解的bean方法被調(diào)用,其實(shí)調(diào)用首先發(fā)生在代理對(duì)象上,先到達(dá)cacheInterceptor,然后才是目標(biāo)bean方法的調(diào)用;
- cacheInterceptor既處理調(diào)用前緩存操作,也處理調(diào)用返回時(shí)緩存操作
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot實(shí)戰(zhàn)權(quán)限管理功能圖文步驟附含源碼
這篇文章主要為大家介紹了springboot實(shí)戰(zhàn)權(quán)限管理功能圖文步驟及示例源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
解決CentOS7中運(yùn)行jar包報(bào)錯(cuò):xxx(Permission?denied)
在實(shí)際工作我們經(jīng)常會(huì)在linux上運(yùn)行Spring boot編寫(xiě)的微服務(wù)程序,下面這篇文章主要給大家介紹了關(guān)于如何解決CentOS7中運(yùn)行jar包報(bào)錯(cuò):xxx(Permission?denied)的相關(guān)資料,需要的朋友可以參考下2024-02-02
Java 本地方法Native Method詳細(xì)介紹
這篇文章主要介紹了 Java 本地方法Native Method詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02
Java實(shí)現(xiàn)ModbusTCP通信功能
使用ModbusTCP實(shí)現(xiàn)和硬件設(shè)備通信功能,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08

