啟用Spring緩存:
Spring配置文件專門為緩存提供了一個cache:命名空間赌渣,為了啟用Spring緩存世落,需要在配置文件中導入cache:命名空間淮腾。導入context:命名空間后,啟用Spring緩存還要兩步屉佳。
- 在Spring配置文件中添加<cache:annotation-driven cache-manager="緩存管理器ID"/>谷朝,該元素指定Spring根據(jù)注解來啟用Bean級別或方法級別的緩存。
- 針對不同的緩存實現(xiàn)配置對應的緩存管理器忘古。
1、Spring內(nèi)置緩存實現(xiàn)的配置:
Spring內(nèi)置的緩存實現(xiàn)只是一種內(nèi)存中的緩存诅诱,并非真正的緩存實現(xiàn)髓堪,因此通常只能用于簡單的測試環(huán)境,不建議在實際項目中使用Spring內(nèi)置緩存的實現(xiàn)娘荡。Spring內(nèi)置的緩存實現(xiàn)使用SimpleCacheManager作為緩存管理器干旁,使用SimpleCacheManager配置緩存非常簡單,直接在Spring容器中配置該Bean炮沐,然后通過<property.../>驅(qū)動該緩存管理器執(zhí)行setCaches()方法來設置緩存區(qū)即可争群。
SimpleCacheManager是一種內(nèi)存中的緩存區(qū),底層直接使用了JDK的ConcurrentMap來實現(xiàn)緩存大年,SimpleCacheManager使用了ConcurrentMapCacheFactoryBean作為緩存區(qū)换薄,每個ConcurrentMapCacheFactoryBean配置一個緩存區(qū)。
<!--使用SimpleCacheManager配置Spring內(nèi)置的緩存管理器-->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<!--配置緩存區(qū)-->
<property name="caches">
<set>
<!--使用ConcurrentMapCacheFactoryBean配置緩存區(qū)翔试,下面列出多個緩存區(qū)轻要,p:name用于緩存區(qū)指定名字-->
<bean class="org.springframework.cache.ConcurrentMapCacheFactoryBean" p:name="defaule"/>
<bean class="org.springframework.cache.ConcurrentMapCacheFactoryBean" p:name="users"/>
</set>
</property>
</bean>
2、EhCache緩存實現(xiàn)的配置:
在配置EhCache緩存實現(xiàn)之前垦缅,首先需要將EhCache緩存的JAR包添加到類加載路徑中冲泥。只要將Hibernate解壓路徑下 lib\optional\ehcache\路徑下的ehcache-core-2.4.3.jar和slf4j-api-1.6.1.jar復制到項目類加載路徑下即可。
為了使用EhCache壁涎,同樣需要在應用的類加載路徑下添加一個ehcache.xml配置文件凡恍。如下配置兩個緩存區(qū):
ehcache.xml
<?xml version="1.0" encoding="gbk"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache name="users"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
使用@Cacheable執(zhí)行緩存:
@cacheable可用于修飾類或修飾方法,當使用@Cacheable修飾類時怔球,用于高數(shù)Spring在類級別上進行緩存---程序調(diào)用該類的實例的任何方法時都需要緩存嚼酝,而且共享同一個緩存區(qū);當使用@Cacheable修飾方法時竟坛,用于告訴Spring在方法級別上進行緩存---只有當程序調(diào)用該方法時才需要緩存革半。
1碑定、類級別的緩存:
@service("userService")
@Cacheable(value="users")
public class UserServiceImpl implements UserService{
public User getUsersByNameAndAge(String name,int age){
System.out.println("--正在執(zhí)行findUsersByNameAndAge()查詢方法--");
return new User(name,age);
}
public User getAnotherUser(String name,int age){
System.out.println("--正在執(zhí)行findAnotherUser()查詢方法--");
return new User(name,age);
}
}
此處所指的緩存的意義是:當程序第一次調(diào)用該類的實例的某個方法時,Spring緩存機制會將該方法返回的數(shù)據(jù)放入指定的緩存區(qū)---就是@Cacheable注解的value屬性值所指定的緩存區(qū)(注意此處指定的數(shù)據(jù)放入users緩存區(qū)又官,這就要求前面為緩存管理器配置過users的緩存區(qū))延刘。以后程序調(diào)用該類的實例的任何方法時,只要傳入的參數(shù)相同六敬,Spring將不會真正指定該方法碘赖,而是直接利用緩存區(qū)中的數(shù)據(jù)。
public class SpringTest{
public static void main(String[] args){
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserService us=ctx.getBean("userService",UserService.class);
//第一次調(diào)用us對象的方法時會執(zhí)行該方法外构,并緩存該方法的結(jié)果
User u1=us.getUserNynameAndAge("張三",500);
//第二次調(diào)用us對象的方法時直接利用緩存的數(shù)據(jù)普泡,并不真正執(zhí)行該方法
User u2=us.getAnotherUser("張三","500");
System.out.println(u1==u2);
}
}
輸出:
--正在執(zhí)行findUsersByNameAndAge()查詢方法--
true
類級別的緩存默認以所有方法的參數(shù)作為key來緩存方法返回的數(shù)據(jù)---同一個類不管調(diào)用哪個方法,只要調(diào)用方法時傳入的參數(shù)相同审编,Spring都會直接利用緩存區(qū)中的數(shù)據(jù)撼班。使用@Cacheable時可指定如下屬性:
- value:必須屬性。該屬性可指定多緩沖區(qū)的名字垒酬,用于指定將方法返回值放入指定的緩存區(qū)內(nèi)砰嘁。
- key:通過SpEL表達式顯示指定緩存的key.
- condition:該屬性指定一個返回boolean值得SpEL表達式,只有當該表達式返回true是勘究,Spring才會緩存方法的返回值矮湘。
- unless:該屬性指定一個返回boolean值得SpEL表達式,當表達式返回true時口糕,Spring就不緩存返回值缅阳。
與@Cacheable注解功能類似的還有一個@CachePut注解,@CachePut注解同樣會讓Spring將方法返回值放入緩沖區(qū)景描。與@Cacheable不同的是十办,@CachePut修飾的方法不會讀取緩存區(qū)中的數(shù)據(jù)---這意味著不管緩存區(qū)是否有數(shù)據(jù),@CachePut總會告訴Spring要重新執(zhí)行這些方法超棺,并再次將方法返回值放入緩沖區(qū)橘洞。
condition屬性與unless屬性的功能基本相似,但規(guī)則恰好相反:當condtion指定的條件為true時说搅,Spring緩存機制才會執(zhí)行緩存炸枣;當unless指定的條件為true時,Spring緩存機制就不執(zhí)行緩存弄唧。
@service("userService")
@Cacheable(value="users" condition="#age<100")
public class UserServiceImpl implements UserService{...}
public class SpringTest{
public static void main(String[] args){
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserService us=ctx.getBean("userService",UserService.class);
//調(diào)用方法時age參數(shù)不小于100适肠,因此不會緩存
User u1=us.getUsersByNameAndAge("張三",500);
User u2=us.getAnotherUser("張三",500);
System.out.println(u1==u2);//輸出false
//調(diào)用方法時age參數(shù)小于100,因此會緩存
User u3=us.getUsersByNameAndAge("張三",50);
User u4=us.getAnotherUser("張三",50);
System.out.println(u3==u4);//輸出true
}
}
2候引、方法級別的緩存:
使用@Caheable修飾方法時侯养,就可以控制Spring在方法級別進行緩存,這樣當程序調(diào)用該方法時澄干,只要傳入的參數(shù)相同逛揩,Spring就會使用緩存柠傍。
@service("userService")
public class UserServiceImpl implements UserService{
@Cacheable(value="user1")
public User getUsersByNameAndAge(String name,int age){
System.out.println("--正在執(zhí)行findUsersByNameAndAge()查詢方法--");
return new User(name,age);
}
@Cacheable(value="user2")
public User getAnotherUser(String name,int age){
System.out.println("--正在執(zhí)行findAnotherUser()查詢方法--");
return new User(name,age);
}
}
上面兩個程序分別使用了users1、users2兩個緩存區(qū)辩稽,因此還需要在ehcache.xml文件中配置這兩個緩存區(qū)惧笛。
public class SpringTest{
public static void main(String[] args){
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
UserService us=ctx.getBean("userService",UserService.class);
//第一次調(diào)用us對象的方法時會執(zhí)行該方法,并緩存該方法的結(jié)果
User u1=us.getUserNynameAndAge("張三",500);
//由于getAnotherUser()方法使用另一個緩存區(qū),因此無法使用getUserNynameAndAge()方法緩存的數(shù)據(jù)
User u2=us.getAnotherUser("張三","500");
System.out.println(u1==u2);//返回false
//getAnotherUser()方法已經(jīng)執(zhí)行過一次了,故下面代碼使用緩存
User u3=us.getAnotherUser("張三","500");
System.out.println(u2==u3);//返回true
}
}
使用@CacheEvict清除緩存:
被@CacheEvict注解修飾的方法可用于清除緩存砸民,使用@CacheEvict注解時可指定如下屬性:
- value:必需屬性。用于指定方法用于清除哪個緩存區(qū)的數(shù)據(jù)各谚。
- allEntries:該屬性指定是否清除整個緩存區(qū)的內(nèi)容。
- beforeInvocation:該屬性指定是否在執(zhí)行方法之前清除緩存到千。默認是在方法執(zhí)行成功之后清除緩存昌渤。
- condition:該屬性指定一個SpEL表達式,只有當該表達式為true時才清除緩存憔四。
- key:通過SpEL表達式顯示指定緩存的key膀息。
@service("userService")
@Cacheable(value="users")
public class UserServiceImpl implements UserService{
public User getUsersByNameAndAge(String name,int age){
System.out.println("--正在執(zhí)行findUsersByNameAndAge()查詢方法--");
return new User(name,age);
}
public User getAnotherUser(String name,int age){
System.out.println("--正在執(zhí)行findAnotherUser()查詢方法--");
return new User(name,age);
}
//根據(jù)name、age參數(shù)清除緩存
@CacheEvict(value="users")
public void evictUser(String name,int age){
System.out.println("--正在清空"+name+"加矛,"+age+"對應的緩存--")
}
//指定清除user緩存區(qū)所有的緩存數(shù)據(jù)
@CacheEvict(value="users",allEntries=true)
public void evictALL(){
System.out.println("--正在清除整個緩存--")
}
}