之前写了ssm基于ehcache的配置详解和使用,这里写下基于spring注解方式的使用和详解。
在ssm中如果想使用注解方式,那么需要在配置文件中开启注解支持:
<!--开启缓存的注解功能,否则注解无法生效--> <cache:annotation-driven /> <!-- 声明缓存管理器 --> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehCacheFactory"></property> </bean> <!--指定工厂类及ehcache.xml文件位置--> <bean id="ehCacheFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"/> </bean> 关于ehcache如何配置可看下我之前写的博客,这里就不写了。
spring注解为我们提供了三个注解分别为:
@Cacheable //缓存结果
@CachePut //添加到制定缓存
@CacheEvict //清除缓存
@Caching //spring3.1以后的复合注解,可以批量操作缓存注解
其实在spring3.1之前还有一个注解,后来被废弃了就是:@TriggersRemove //从缓存中移除对象
spring提供的三个注解中存在的属性:
value:必填属性,指定缓存名称,用于操作缓存
condition:非必填,基于springEL表达式进行缓存操作的限制,一般用于Cacheable注解
allEntries:boolean类型,默认false,表示是否清除所有缓存元素
beforeInvocation:boolean类型,非必填,表示清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
注意我们也可以使用ehcache的去除策略最近使用(LRU)"策略,其它还有先入先出FIFO,最少使用LFU,较少使用LRU
另外,spring内置了root对象来辅助我们使用缓存:
methodName 当前方法名 #root.methodName method 当前方法 #root.method.name target 当前被调用的对象 #root.target targetClass 当前被调用的对象的class #root.targetClass args 当前方法参数组成的数组 #root.args[0] caches 当前被调用的方法使用的Cache #root.caches[0].name
注意:所有注解均是基于方法的,要知道springMVC的理念就是面向方法
@Cacheable常用方式:
@Cacheable({"cache1", "cache2"}) //缓存到cache1和cache2中 @Cacheable(value="users", key="#id") //缓存到users中key为其结果ID @Cacheable(value = "employee", condition = "#age < 25")//缓存到employee中,过滤结果集中age字段值小于25的数据 @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")//同上,取模
@Cacheable(value = {"cache1"}, key = "#root.targetClass")// key 当前类,使用root内置对象
该方法一般使用在查询操作上
@CachePut常用方式:
@CachePut(value = "lt.ecache", key = "#id") public Employee updateEmployee(Employee em)//@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") public User conditionSave2(final User user)
该方法一般使用在更新操作上
@CacheEvict常用方式:
@CacheEvict(value = "lt.ecache", key = "#id") public Employee removeEmployee(int id, List<Employee> employees)// 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示例:
@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
@CacheEvict(value = "cache3", allEntries = true) })
public User find(Integer id) {
returnnull;
}
感兴趣的也可以使用自定义注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(value="users")
public @interface MyCacheable {
}
那么在我们需要缓存的方法上使用@MyCacheable进行标注也可以达到同样的效果。
@MyCacheable
public User findById(Integer id) {
return user;
}
以上注解方式均是spring在管理维护,该注解需要我们提供缓存的支持,我这里使用的是ehcache,当然spring也支持redis,个人写的有相关文章可以查看。redis文章中提到了缓存策略,同样ssm中的ehcache也有缓存策略。
默认的key生成策略是通过KeyGenerator生成的,其默认策略如下 如果方法没有参数,则使用0作为key。 如果只有一个参数的话则使用该参数作为key 如果参数多余一个的话则使用所有参数的hashCode作为key。 如果我们需要指定自己的默认策略的话,那么我们可以实现自己的KeyGenerator,然后指定我们的Spring Cache使用的KeyGenerator为我们自己定义的KeyGenerator。 使用基于注解的配置时是通过cache:annotation-driven指定的. <cache:annotation-driven key-generator="userKeyGenerator"/> <bean id="userKeyGenerator" class="com.xxx.cache.UserKeyGenerator"/>
而使用基于XML配置时是通过cache:advice来指定的。 <cache:advice id="cacheAdvice" cache-manager="cacheManager" key-generator="userKeyGenerator"> </cache:advice>
需要注意的是此时我们所有的Cache使用的Key的默认生成策略都是同一个KeyGenerator。
具体策略使用方法根据个人情况而定,可自行查找资料。
使用注解方式可以避免我在上一篇ehcache文章中遗留的事务疑问。
其实ehcache内部也有事务机制,感兴趣的可以深究一下文章:https://www.cnblogs.com/yaohonv/archive/2012/02/10/JTA-Ehcache.html
如有不足或错误,请各位大佬指点