Spring缓存注解@Cache使⽤
@Cacheable
  @Cacheable 的作⽤主要针对⽅法配置,能够根据⽅法的请求参数对其结果进⾏缓存
@Cacheable 作⽤和配置⽅法
参数解释example
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个例如:
@Cacheable(value=”mycache”)
@Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照⽅法的所
有参数进⾏组合
@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才进⾏缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)实例
  @Cacheable(value=”accountCache”),这个注释的意思是,当调⽤这个⽅法的时候,会从⼀个名叫 accountCache 的缓存中查询,如果没有,则执⾏实际的⽅法(即查询),并将执⾏的结果存⼊缓存中,否则返回缓存中的对象。这⾥的缓存中的 key 就是参数 userName,value 就是 Account 对象。“accountCache”缓存是在
spring*.xml 中定义的名称。
@Cacheable(value="accountCache")// 使⽤了⼀个缓存名叫 accountCache
public Account getAccountByName(String userName) {
// ⽅法内部实现不考虑缓存逻辑,直接实现业务
System.out.println("real query account."+userName);
return getFromDB(userName);
}
@CachePut
@CachePut 的作⽤主要针对⽅法配置,能够根据⽅法的请求参数对其结果进⾏缓存,和 @Cacheable 不同的是,它每次都会触发真实⽅法的调⽤
@CachePut 作⽤和配置⽅法
参数解释example
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个@CachePut(value=”my cache”)
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照⽅法的所有
参数进⾏组合
@CachePut(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才进⾏缓存@CachePut(value=”testcache”,condition=”#userName.length()>2”)实例
@CachePut 注释,这个注释可以确保⽅法被执⾏,同时⽅法的返回值也被记录到缓存中,实现缓存与
数据库的同步更新。
@CachePut(value="accountCache",key="#Name()")// 更新accountCache 缓存
public Account updateAccount(Account account) {
return updateDB(account);
}
@CacheEvict (清空缓存)
@CachEvict 的作⽤主要针对⽅法配置,能够根据⼀定的条件对缓存进⾏清空
@CacheEvict 作⽤和配置⽅法
参数解释example
value缓存的名称,在 spring 配置⽂件中定义,必须指定⾄少⼀个@CacheEvict(value=”my cache”)
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照⽅
法的所有参数进⾏组合
@CacheEvict(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使⽤ SpEL 编写,返回 true 或者 false,只有为 true 才进⾏缓存@CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则⽅法调⽤后将⽴即清空所有
缓存
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation是否在⽅法执⾏前就清空,缺省为 false,如果指定为 true,则在⽅法还没有执⾏的时候
就清空缓存,缺省情况下,如果⽅法执⾏抛出异常,则不会清空缓存
@CachEvict(value=”testcache”,beforeInvocation=true)
实例
@CacheEvict(value="accountCache",key="#Name()")// 清空accountCache 缓存
public void updateAccount(Account account) {
updateDB(account);
}
@CacheEvict(value="accountCache",allEntries=true)// 清空accountCache 缓存
public void reload() {
reloadAll()
}
@Cacheable(value="accountCache",condition="#userName.length() <=4")// 缓存名叫 accountCache
public Account getAccountByName(String userName) {
// ⽅法内部实现不考虑缓存逻辑,直接实现业务
return getFromDB(userName);
}
@CacheConfig
所有的@Cacheable()⾥⾯都有⼀个value=“xxx”的属性,这显然如果⽅法多了,写起来也是挺累的,如果可以⼀次性声明完那就省事了,
所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的⽅法写别的名字,那么依然以⽅法的名字为准。
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
条件缓存
下⾯提供⼀些常⽤的条件缓存
//@Cacheable将在执⾏⽅法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存;
@Cacheable(value = "user", key = "#id", condition = "#id lt 10")
public User conditionFindById(final Long id)
//@CachePut将在执⾏完⽅法后(#result就能拿到返回值了)判断condition,如果返回true,则放⼊缓存;
@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")
public User conditionSave(final User user)
//@CachePut将在执⾏完⽅法后(#result就能拿到返回值了)判断unless,如果返回false,则放⼊缓存;(即跟condition相反)
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")
public User conditionSave2(final User user)
//@CacheEvict, beforeInvocation=false表⽰在⽅法执⾏之后调⽤(#result能拿到返回值了);且判断condition,如果返回true,则移除缓存;
@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'")
public User conditionDelete(final User user)
@Caching
有时候我们可能组合多个Cache注解使⽤;⽐如⽤户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#ail")
})
public User save(User user) {
⾃定义缓存注解
⽐如之前的那个@Caching组合,会让⽅法上的注解显得整个代码⽐较乱,此时可以使⽤⾃定义注解把这些注解组合到⼀个注解中,如:
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#ail")
})
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface UserSaveCache {
}
这样我们在⽅法上使⽤如下代码即可,整个代码显得⽐较⼲净。
@UserSaveCache
public User save(User user)
扩展
⽐如findByUsername时,不应该只放username–>user,应该连同id—>user和email—>user⼀起放⼊;这样下次如果按照id查直接从缓存中就命中了
@Caching(
cacheable = {
@Cacheable(value = "user", key = "#username")
},
put = {
@CachePut(value = "user", key = "#result.id", condition = "#result != null"),
@CachePut(value = "user", key = "#ail", condition = "#result != null")
}
)
public User findByUsername(final String username) {
System.out.println("cache miss, invoke find by username, username:" + username);
for (User user : users) {
if (Username().equals(username)) {
return user;
}
}
return null;
}
其实对于:id—>user;username—->user;email—>user;更好的⽅式可能是:id—>user;username—>id;email—>id;保证user只存⼀份;如:
@CachePut(value="cacheName", key="#user.username", cacheValue="#user.username")
public void save(User user)
@Cacheable(value="cacheName", key="#user.username", cacheValue="#caches[0].get(#caches[0].get(#username).get())")
public User findByUsername(String username)
SpEL上下⽂数据
Spring Cache提供了⼀些供我们使⽤的SpEL上下⽂数据,下表直接摘⾃Spring官⽅⽂档:
名称位置描述⽰例
methodName root对象当前被调⽤的⽅法名hodName
method root对象当前被调⽤的⽅法hod.name
target root对象当前被调⽤的⽬标对象root.target
targetClass root对象当前被调⽤的⽬标对象类root.targetClass
args root对象当前被调⽤的⽅法的参数列表root.args[0]
caches root对象当前⽅法调⽤使⽤的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cache root.caches[0].name
argument name执⾏上下⽂当前被调⽤的⽅法的参数,如findById(Long id),我们可以通过#id拿到参数user.id
result执⾏上下⽂⽅法执⾏后的返回值(仅当⽅法执⾏之后的判断有效,如‘unless’,’cache evict’的beforeInvocation=false)result
@CacheEvict(value = "user", key = "#user.id", condition = "#root.target.canCache() and #root.caches[0].get(#user.id).get().username ne #user.username", beforeInvocation = public void conditionUpdate(User user)
--------------------⾃⼰写的⼀个实例------------------------
查询的时候增加缓存,增加的时候删除缓存。
@Autowired
private UserMapper userMapper;
@Cacheable(value="findAllUser")//在redis中开启key为findAllUser的存储空间
public List<User> findAllUser(Map condition) {
System.out.println("打印语句则没有⾛缓存");
List<User> list = userMapper.findAll();
return list;
}
@Override
@CacheEvict(value="findAllUser",allEntries=true)
public int addUser() throws SQLException {
// TODO Auto-generated method stub
cacheable
return userMapper.addUser();
}
解释:
  1.上⾯根据⽅法的参数判断是否有缓存,当参数不同的时候会增加缓存,前⾯的findAllUser是缓存key的前缀,例如:findAllUser:XXXXX。后⾯的XXXX是spring根
据参数⾃动⽣成的。
  2.执⾏add⽅法会删除上⾯以findAllUser:开始的所有的缓存(也就是删除上⾯的三个缓存),findAllUser可以叫做缓存名称。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。