⑴ spring cache 註解 緩存名有什麼用
來看下@Cacheable 的說明
@Cacheable(value="accountCache"),這個注釋的意思是,當調用這個方法的時候,會從一個名叫 accountCache 的緩存中查詢,如果沒有,則執行實際的方法(即查詢資料庫),並將執行的結果存入緩存中,否則返回緩存中的對象。這里的緩存中的 key 就是參數 userName,value 就是 Account 對象。「accountCache」緩存是在 spring*.xml 中定義的名稱。
示例:
@Cacheable(value="accountCache")//使用了一個緩存名叫accountCache
publicAccountgetAccountByName(StringuserName){
//方法內部實現不考慮緩存邏輯,直接實現業務
System.out.println("realqueryaccount."+userName);
returngetFromDB(userName);
}
主要作用是給 cache 取個名稱
⑵ spring 如何解決循環依賴,為什麼要創建三個緩存
spring是如何解決單例的循環依賴注入
首先看下面三個緩存:
1.singletonObjects:存放初始化好的bean
2.earlySingletonObjects:存放了剛實例化好的,但是還未配置屬性和初始化的bean,我們在獲取該bean的時候會調用beanPostProcessor的getEarlyReference進行一些提前獲取bean的必要操作
3.singletonFactories:存放我剛實例化的bean,通過ObjectFactory,可以讓如果有提前需要bean的需要可以調用該
objectfactory 其會將剛實例化好的bean經過beanPostProcessor的getEarlyReference處理進行返回
我們先實例化A,實例化好後
調用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
() -> getEarlyBeanReference(beanName, mbd, bean)是objectFactory的實現匿名類,然後此時我們設置屬性的時候會發現我們還依賴B,於是我們去實例化B而當我們此時實例化B的會經過下面這個方法
由此可見 如果之前已經把A存放在singletonFactories,那麼B會把其調出來放入earlySingletonObjects,然後整個單例創建完成在塞入singletonObjects。存放在singletonFactories好處是可擴展,我們在這個裡面會調用beanPostProcessor 從而可以在我們實現提前獲取對象引用的時候進行一些操作
⑶ windows環境下Redis+Spring緩存實例
一、Redis了解
1.1、Redis介紹:
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set –有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis資料庫完全在內存中,使用磁碟僅用於持久性。相比許多鍵值數據存儲,Redis擁有一套較為豐富的數據類型。Redis可以將數據復制到任意數量的從伺服器。
1.2、Redis優點:
(1)異常快速:Redis的速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄。
(2)支持豐富的數據類型:Redis支持最大多數開發人員已經知道像列表,集合,有序集合,散列數據類型。這使得它非常容易解決各種各樣的問題,因為我們知道哪些問題是可以處理通過它的數據類型更好。
(3)操作都是原子性:所有Redis操作是原子的,這保證了如果兩個客戶端同時訪問的Redis伺服器將獲得更新後的值。
(4)多功能實用工具:Redis是一個多實用的工具,可以在多個用例如緩存,消息,隊列使用(Redis原生支持發布/訂閱),任何短暫的數據,應用程序,如Web應用程序會話,網頁命中計數等。
1.3、Redis缺點:
(1)單線程
(2)耗內存
二、64位windows下Redis安裝
Redis官方是不支持windows的,但是Microsoft Open Tech group 在 GitHub上開發了一個Win64的版本,下載地址:https://github.com/MSOpenTech/redis/releases。注意只支持64位哈。
小寶鴿是下載了Redis-x64-3.0.500.msi進行安裝。安裝過程中全部採取默認即可。
安裝完成之後可能已經幫你開啟了Redis對應的服務,博主的就是如此。查看資源管理如下,說明已經開啟:
已經開啟了對應服務的,我們讓它保持,下面例子需要用到。如果沒有開啟的.,我們命令開啟,進入Redis的安裝目錄(博主的是C:Program FilesRedis),然後如下命令開啟:
redis-server redis.windows.conf
OK,下面我們進行實例。
三、詳細實例
本工程採用的環境:Eclipse + maven + spring + junit
3.1、添加相關依賴(spring+junit+redis依賴),pom.xml:
4.0.0 com.luo redis_project 0.0.1-SNAPSHOT 3.2.8.RELEASE 4.10 org.springframework spring-core ${spring.version} org.springframework spring-webmvc ${spring.version} org.springframework spring-context ${spring.version} org.springframework spring-context-support ${spring.version} org.springframework spring-aop ${spring.version} org.springframework spring-aspects ${spring.version} org.springframework spring-tx ${spring.version} org.springframework spring-jdbc ${spring.version} org.springframework spring-web ${spring.version} junit junit ${junit.version} test org.springframework spring-test ${spring.version} test org.springframework.data spring-data-redis 1.6.1.RELEASE redis.clients jedis 2.7.3
3.2、spring配置文件application.xml:
<"1.0" encoding="UTF-8"> classpath:properties/*.properties
3.3、Redis配置參數,redis.properties:
#redis中心#綁定的主機地址redis.host=127.0.0.1#指定Redis監聽埠,默認埠為6379redis.port=6379#授權密碼(本例子沒有使用)redis.password=123456 #最大空閑數:空閑鏈接數大於maxIdle時,將進行回收redis.maxIdle=100 #最大連接數:能夠同時建立的「最大鏈接個數」redis.maxActive=300 #最大等待時間:單位msredis.maxWait=1000 #使用連接時,檢測連接是否成功 redis.testOnBorrow=true#當客戶端閑置多長時間後關閉連接,如果指定為0,表示關閉該功能redis.timeout=10000
3.4、添加介面及對應實現RedisTestService.Java和RedisTestServiceImpl.java:
package com.luo.service; public interface RedisTestService { public String getTimestamp(String param);}
package com.luo.service.impl; import org.springframework.stereotype.Service;import com.luo.service.RedisTestService; @Servicepublic class RedisTestServiceImpl implements RedisTestService { public String getTimestamp(String param) { Long timestamp = System.currentTimeMillis(); return timestamp.toString(); } }
3.5、本例採用spring aop切面方式進行緩存,配置已在上面spring配置文件中,對應實現為MethodCacheInterceptor.java:
package com.luo.redis.cache; import java.io.Serializable;import java.util.concurrent.TimeUnit;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations; public class MethodCacheInterceptor implements MethodInterceptor { private RedisTemplate redisTemplate; private Long defaultCacheExpireTime = 10l; // 緩存默認的過期時間,這里設置了10秒 public Object invoke(MethodInvocation invocation) throws Throwable { Object value = null; String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); Object[] arguments = invocation.getArguments(); String key = getCacheKey(targetName, methodName, arguments); try { // 判斷是否有緩存 if (exists(key)) { return getCache(key); } // 寫入緩存 value = invocation.proceed(); if (value != null) { final String tkey = key; final Object tvalue = value; new Thread(new Runnable() { public void run() { setCache(tkey, tvalue, defaultCacheExpireTime); } }).start(); } } catch (Exception e) { e.printStackTrace(); if (value == null) { return invocation.proceed(); } } return value; } /** * 創建緩存key * * @param targetName * @param methodName * @param arguments */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuffer sbu = new StringBuffer(); sbu.append(targetName).append("_").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sbu.append("_").append(arguments[i]); } } return sbu.toString(); } /** * 判斷緩存中是否有對應的value * * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 讀取緩存 * * @param key * @return */ public Object getCache(final String key) { Object result = null; ValueOperations operations = redisTemplate .opsForValue(); result = operations.get(key); return result; } /** * 寫入緩存 * * @param key * @param value * @return */ public boolean setCache(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations operations = redisTemplate .opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public void setRedisTemplate( RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; }}
3.6、單元測試相關類:
package com.luo.baseTest; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //指定bean注入的配置文件 @ContextConfiguration(locations = { "classpath:application.xml" }) //使用標準的JUnit @RunWith注釋來告訴JUnit使用Spring TestRunner @RunWith(SpringJUnit4ClassRunner.class) public class SpringTestCase extends { }
package com.luo.service; import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired; import com.luo.baseTest.SpringTestCase; public class RedisTestServiceTest extends SpringTestCase { @Autowired private RedisTestService redisTestService; @Test public void getTimestampTest() throws InterruptedException{ System.out.println("第一次調用:" + redisTestService.getTimestamp("param")); Thread.sleep(2000); System.out.println("2秒之後調用:" + redisTestService.getTimestamp("param")); Thread.sleep(11000); System.out.println("再過11秒之後調用:" + redisTestService.getTimestamp("param")); } }
3.7、運行結果:
四、源碼下載:redis-project().rar
以上就是本文的全部內容,希望對大家的學習有所幫助。
⑷ SpringBoot整合SpringSeesion實現Redis緩存
使用Spring Boot開發項目時我們經常需要存儲Session,因為Session中會存一些用戶信息或者登錄信息。傳統的web服務是將session存儲在內存中的,一旦服務掛了,session也就消失了,這時候我們就需要將session存儲起來,而Redis就是用來緩存seesion的一種非關系型資料庫,我們可以通過配置或者註解的方式將Spring Boot和Redis整合。而在分布式系統中又會涉及到session共享的問題,多個服務同時部署時session需要共享,Spring Session可以幫助我們實現這一功能。將Spring Session集成到Spring Boot框架中並使用Redis進行緩存是目前非常流行的解決方案,接下來就跟著我一起學習吧。
工具/材料
IntelliJ IDEA
首先我們創建一個Spring Boot 2.x的項目,在application.properties配置文件中添加Redis的配置,Spring和Redis的整合可以參考我其他的文章,此處不再詳解。我們設置服務埠server.port為8080埠用於啟動第一個服務。
接下來我們需要在pom文件中添加spring-boot-starter-data-redis和spring-session-data-redis這兩個依賴,spring-boot-starter-data-redis用於整合Spring Boot和Redis,spring-session-data-redis集成了spring-session和spring-data-redis,提供了session與redis的整合方案。
接下來我們創建一個配置類RedisSessionConfig,這個類使用@Configuration註解表明這是一個配置類。在這個類上我們同時添加註解@EnableRedisHttpSession,表示開啟Redis的Session管理。如果需要設置失效時間可以使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)表示一小時後失效。若同時需要設置Redis的命名空間則使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds=3600, redisNamespace="{spring.session.redis.namespace}") ,其中{spring.session.redis.namespace}表示從配置文件中讀取這個命名空間。
配置完成後我們寫一個測試類SessionController,在這個類中我們寫兩個方法,一個方法用於往session中存數據,一個用於從session中取數據,代碼如下圖所示,我們存取請求的url。啟動類非常簡單,一般都是通用的,我們創建一個名為SpringbootApplication的啟動類,使用main方法啟動。
接下來我們使用Postman分別請求上面兩個介面,先請求存數據介面,再請求取數據介面,結果如下圖所示,我們可以看到數據已從redis中取出。另外需要注意sessionId的值,這是session共享的關鍵。
為了驗證兩個服務是否共享了session,我們修改項目的配置文件,將服務埠server.port改為8090,然後再啟動服務。此時我們不必在請求存數據的介面,只需要修改請求埠號再一次請求取數據的介面即可。由下圖可以看到兩次請求的sessionId值相同,實現了session的共享。
以上我們完成了SpringBoot整合SpringSeesion實現Redis緩存的功能,在此我們還要推薦一個Redis的可視化工具RedisDesktopManager,我們可以配置Redis資料庫的連接,然後便可以非常直觀地查看到存儲到Redis中的session了,如下圖所示,session的命名空間是share,正是從配置文件中讀取到的。
特別提示
如果Redis伺服器是很多項目共用的,非常建議配置命名空間,否則同時打開多個項目的瀏覽器頁面可能會導致session錯亂的現象。
⑸ hibernate二級緩存 和 spring整合的緩存(就是用哪個Cacheable註解的)有什麼區別么
二級緩存配置(spring+hibernate)
說明:本人不建議使用查詢緩存,因為查詢緩存要求完全相同的查詢sql語句才會起作用,所說的查詢緩存是針對第二次查詢時 sql語句與第一次sql語句完全相同 那麼就可以從緩存中取數據而不去資料庫中取數據了,在不啟用查詢緩存的情況下 每次的查詢數據也會緩存到二級緩存的 只不過每次查詢都會去查詢資料庫(不包括根據ID查詢),啟用查詢緩存很麻煩 需要每次查詢時 調用Query.setCacheable(true)方法才可以,如:List<OrgiData> orgiDatas = (List<OrgiData>) s.createQuery("from OrgiData").setCacheable(true).list();
因此建議將查詢緩存設置為如下:
hibernate.cache.use_query_cache=false
還有就是最重要的一點:對於經常修改或重要的數據不宜進行緩存,因為多並發時會造成數據不同步的情況。
首先增加ehcache-1.4.1.jar和backport-util-concurrent-3.1.jar或oscache-2.1.jar
一、spring配置
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>com/handpay/core/merchant/bean/MerchGroupBuy.hbm.xml
</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=false
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider </value>
</property>
</bean>
<!---紅色字體是二級緩存相關的設置->
二、hbm.xml文件示例
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.handpay.core.merchant.bean">
<class name="MerchGroupBuy" table="merch_group_buy">
<cache usage="read-write" region="com.handpay.core.merchant.bean.MerchGroupBuy"/>
<id name="id">
<generator class="native" />
</id>
<property name="code" />
<property name="createTime"/>
<property name="minNum"/>
<property name="status">
</property>
<property name="title"/>
<property name="typeCode"/>
<property name="updateTime"/>
</class>
</hibernate-mapping>
三、註解示例
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Table(name = "alcor_t_countries", catalog = "alcorweb")
public class AlcorTCountries implements java.io.Serializable{。。。。}
四、配置文件參數詳解
ehcache.xml是ehcache的配置文件,並且存放在應用的classpath中。下面是對該XML文件中的一些元素及其屬性的相關說明:
<diskStore>元素:指定一個文件目錄,當EHCache把數據寫到硬碟上時,將把數據寫到這個文件目錄下。 下面的參數這樣解釋:
user.home – 用戶主目錄
user.dir – 用戶當前工作目錄
java.io.tmpdir – 默認臨時文件路徑
<defaultCache>元素:設定緩存的默認數據過期策略。
<cache>元素:設定具體的命名緩存的數據過期策略。
<cache>元素的屬性
name:緩存名稱。通常為緩存對象的類名(非嚴格標准)。
maxElementsInMemory:設置基於內存的緩存可存放對象的最大數目。
maxElementsOnDisk:設置基於硬碟的緩存可存放對象的最大數目。
eternal:如果為true,表示對象永遠不會過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認為false;
timeToIdleSeconds: 設定允許對象處於空閑狀態的最長時間,以秒為單位。當對象自從最近一次被訪問後,如果處於空閑狀態的時間超過了timeToIdleSeconds屬性值,這個對象就會過期。當對象過期,EHCache將把它從緩存中清空。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限期地處於空閑狀態。
timeToLiveSeconds:設定對象允許存在於緩存中的最長時間,以秒為單位。當對象自從被存放到緩存中後,如果處於緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期。當對象過期,EHCache將把它從緩存中清除。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限期地存在於緩存中。timeToLiveSeconds必須大於timeToIdleSeconds屬性,才有意義。
overflowToDisk:如果為true,表示當基於內存的緩存中的對象數目達到了maxElementsInMemory界限後,會把益出的對象寫到基於硬碟的緩存中。注意:如果緩存的對象要寫入到硬碟中的話,則該對象必須實現了Serializable介面才行。
memoryStoreEvictionPolicy:緩存對象清除策略。有三種:
1 FIFO ,first in first out ,這個是大家最熟的,先進先出,不多講了
2 LFU , Less Frequently Used ,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的。如上面所講,緩存的元素有一個hit 屬性,hit 值最小的將會被清出緩存。
2 LRU ,Least Recently Used ,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。
五 、查看 二級緩存數據
1、使用sessionFactory直接獲取
Map cacheEntries = sessionFactory().getStatistics()
.getSecondLevelCacheStatistics("cacheRegionName")
.getEntries();
其中 cacheRegionName 既是 ehcache.xml配置中的<cache 標簽的name屬性值
2、讓log4j列印緩存信息(生成環境下請注釋掉,以免影響性能)
log4j.logger.org.hibernate.cache=debug
⑹ Spring本地緩存的使用方法
我們現在在用的Spring Cache,可以直接看Spring Boot提供的緩存枚舉類,有如下這些:
EhCache:一個純Java的進程內緩存框架,所以也是基於本地緩存的。(注意EhCache2.x和EhCache3.x相互不兼容)。
Redis:分布式緩存,只有Client-Server(CS)模式,Java一般使用Jedis/Luttuce來操縱。
Hazelcast:基於內存的數據網格。雖然它基於內存,但是分布式應用程序可以使用Hazelcast進行分布式緩存、同步、集群、處理、發布/訂閱消息等。
Guava:它是Google Guava工具包中的一個非常方便易用的本地化緩存實現,基於LRU(最近最少使用)演算法實現,支持多種緩存過期策略。在Spring5.X以後的版本已經將他標記為過期了。
Caffeine:是使用Java8對Guava緩存的重寫版本,在Spring5中將取代了Guava,支持多種緩存過期策略。
SIMPLE:使用ConcurrentMapCacheManager,因為不支持緩存過期時間,所以做本地緩存基本不考慮該方式。
關於分布式緩存,我們需要後面會專門討論Redis的用法,這里只看本地緩存。性能從高到低,依次是Caffeine,Guava,ConcurrentMapCacheManager,其中Caffeine在讀寫上都快了Guava近一倍。
這里我們只討論在Spring Boot裡面怎麼整合使用Caffeine和EhCache。
主要有以下幾個步驟:
1)加依賴包:
2)配置緩存:
這里有兩種方法,通過文件配置或者在配置類裡面配置,先看一下文件配置,我們可以寫一個properties文件,內容像這樣:
然後還要在主類中加上@EnableCaching註解:
另外一種更靈活的方法是在配置類中配置:
應用類:
測試類:
導入依賴包,分為2.x版本和3.x版本。
其中2.x版本做如下導入:
3.x版本做如下導入:
導包完成後,我們使用JCacheManagerFactoryBean + ehcache.xml的方式配置:
參考資料:
https://blog.csdn.net/f641385712/article/details/94982916
http://www.360doc.com/content/17/1017/20/16915_695800687.shtml
⑺ springboot緩存怎麼來操作
1.在pom.xml中引入cache依賴,添加如下內容:
復制代碼
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
復制代碼
2.在Spring Boot主類中增加@EnableCaching註解開啟緩存功能,如下:
復制代碼
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
復制代碼
3.在數據訪問介面中,增加緩存配置註解,如:
復制代碼
@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Long> {
@Cacheable
User findByName(String name);
}
復制代碼
SpringBoot支持很多種緩存方式:redis、guava、ehcahe、jcache等等。