spring--springCache

###1、spring提供以下注解来支持spring cache
####1.@Cacheable
使用@Cacheable标记的方法,在执行该方法时,spring先去缓存中查询一次,若是查询到结果,直接返回结果(即该方法实际不会被执行);不然,执行该方法,将结果缓存。
@Cacheable能够标记在一个方法(表示该方法支持缓存)或标记在一个类上(该类的全部方法均支持缓存)
须要注意的是:支持缓存的方法在对象内部被调用时是不会触发缓存功能的
@Cacheable指定属性有:
value 缓存空间名称
key 缓存的key,根据这个key去上述缓存空间中查询对象值
condition 缓存的条件,能够为空。可使用spel编写返回true或false,只有true时才进行缓存 ####2.@CachePut
使用@CachePut标记的方法,在执行该方法时,每次都执行实际方法,将结果缓存。
####3.@CacheEvict
使用@CacheEvict标记的方法,会在方法执行以前或以后移除springCache中某些元素
@CacheEvict指定的属性有:
value:缓存空间名称
key:缓存的key
condition:缓存条件
allEntries:是否清空全部缓存内容,缺省值为false,若是指定true,则方法调用后当即清除全部的缓存
beforeInvocation:是否在执行方法以前就清空全部的缓存,缺省值false,若是指定true,则方法尚未执行前就清空缓存;缺省状况下,若是方法抛出异常,则不会清空缓存
####4.@Caching
它可让咱们在一个方法或类上同时指定多个spring cache相关注解java

###2、实际例子
基于上一篇《纯java实现缓存》,咱们这里从新定义业务类(MyAccountService)和测试类(Main),自定义的缓存管理器类不须要了,由于spring已经为咱们提供了。
从新定义服务类以下spring

package com.test.spring.cacheCommon;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

/**
 * 业务类 
 */
public class MyAccountService {
	/**
	 * 该注解的意思是:当调用getAccountByName这个方法时,spring会从一个名叫accountCache的缓存空间中查询
	 * 注意:1.这里没有指定查询的key,因此spting默认传参name做为key,value为Account对象。
	 * 2.accountCache这个名称须要在spring的xml文件中配置
	 * 若是查询到了,则直接返回结果,不执行getAccountByName方法
	 * 不然,执行getAccountByName方法,并将查询结果缓存起来
	 */
	@Cacheable(value="accountCache")
	//根据key获取对象值
	public Account getAccountByName(String name){
		Account result = getFromDB(name);
		return result;
	}
	
	/**
	 * 清除这个key值(account.getName())的对象值
	 */
	@CacheEvict(value="accountCache",key="#account.getName()")
	public void updateAccount(Account account){
		
		updateFromDB(account);
		
	}
	
	//数据库查询帐号信息
	private Account getFromDB(String name) {
		System.out.println("去数据库查询");
		return new Account(name);
	}
	
	//更新帐号信息
	private void updateFromDB(Account account){
		System.out.println("更新帐号信息"+account.getName());
	}
}

测试类以下数据库

package com.test.spring.cacheCommon;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试类
 *
 */
public class Main {
	
	public static void main(String[] args) {
		
		ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml");
		
		MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService");
		
		//第一次查询,去数据库查询
		myAccountService.getAccountByName("张三");
		//第二次查询,从缓存中查询
		myAccountService.getAccountByName("张三");
		
		//清空缓存
		Account account1 = myAccountService.getAccountByName("张三");
		myAccountService.updateAccount(account1);
		
		//第三次查询,从数据库查询
		myAccountService.getAccountByName("张三");
		//第四次查询,从缓存中查询
		myAccountService.getAccountByName("张三");
	}

}

xml文件配置以下缓存

<!-- 服务bean配置 -->
	<bean id="myAccountService" class="com.test.spring.cacheCommon.MyAccountService"></bean>
	
	<!-- 配置缓存管理器 
		1.它有一个属性caches,即这个管理器全部的空间名称的集合
		2.若是方法上缺省空间名称,则默认为default	
		3.咱们还定义了一个名字叫作 accountCache
		4.使用了缺省的内存方案ConcurrentMapCacheFactoryBean,它是基于java.util.concurrent.ConcurrentHashMap的一个内存缓存实现方法
	-->
	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"></bean>
				<!-- 指定spring缓存空间名称 -->
				<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="accountCache"></bean>
			</set>
		</property>
	</bean>
	<!-- 启用缓存注解 -->
	<cache:annotation-driven cache-manager="cacheManager"/>

输出结果测试

去数据库查询
更新帐号信息张三
去数据库查询

###多个参数时,如何制定key
1.修改基础bean日志

public class Account {
	private int id;
	private String name;
        //新增字段
	private String password;
}

2.业务类code

public class MyAccountService {
	/**
         * 注意 key的组合
	 */
	@Cacheable(value="accountCache",key="#name.concat(#password)")
	//根据key获取对象值
	public Account getAccountByName(String name,String password){
		Account result = getFromDB(name,password);
		return result;
	}
	
	//数据库查询帐号信息
	private Account getFromDB(String name,String password) {
		System.out.println("去数据库查询");
		return new Account(name,password);
	}
}

3.测试方法xml

public class Main {
	
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml");
		MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService");
		
		//第一次查询,去数据库查询
		myAccountService.getAccountByName("张三","123456");
		//第二次查询,从缓存中查询
		myAccountService.getAccountByName("张三","123456");
		
		
		//第三次查询,从数据库查询
		myAccountService.getAccountByName("张三","654321");
		//第四次查询,从缓存中查询
		myAccountService.getAccountByName("张三","654321");
	}

}

###@CachePut注解使用
实际的工程中,存在这种状况,咱们但愿某一个方法每次执行都必须被调用,由于这个方法不单单只返回结果,还作了其它的事情,好比:记录日志等。所以这个时候要使用@CachePut注解,它能保证该方法必定被执行,同时返回值被记录到缓存中。
业务类对象

package com.test.spring.cacheCommon;

import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;

/**
 * 业务类 
 */
public class MyAccountService {
	/**
	 * key的组合使用
	 */
	@Cacheable(value="accountCache",key="#name.concat(#password)")
	//根据key获取对象值
	public Account getAccountByName(String name,String password){
		Account result = getFromDB(name,password);
		return result;
	}
	
	/**
	 * 
	 * @CachePut使用
	 * 
	 */
	@CachePut(value="accountCache",key="#account.getName()")
	 public Account updateAccount(Account account) { 
	   return updateDB(account); 
	 }
	
	//更新帐号信息
	private Account updateDB(Account account) { 
	   System.out.println("real updating db..."+account.getName()); 
	   return account; 
	}
	
	//数据库查询帐号信息
	private Account getFromDB(String name,String password) {
		System.out.println("去数据库查询");
		return new Account(name,password);
	}
}

测试类内存

package com.test.spring.cacheCommon;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试类
 *
 */
public class Main {
	
	public static void main(String[] args) {
		
		ApplicationContext ctx = new ClassPathXmlApplicationContext("springCacheCommon.xml");
		
		MyAccountService myAccountService = (MyAccountService) ctx.getBean("myAccountService");
		
		//第一次查询,去数据库查询
		myAccountService.getAccountByName("张三","123456");
		//第二次查询,从缓存中查询
		myAccountService.getAccountByName("张三","123456");
		
		//
		Account account = myAccountService.getAccountByName("张三", "123456");
		myAccountService.updateAccount(account);
		
		//第三次查询,从数据库查询
		myAccountService.getAccountByName("张三","123456");
		
		//第四次查询,从数据库查询
		myAccountService.getAccountByName("张三","654321");
		//第五次查询,从缓存中查询
		myAccountService.getAccountByName("张三","654321");
	}

}

输出结果

去数据库查询
real updating db...张三
去数据库查询
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息