spring整合ehcahce2实现方法返回值缓存

来源:互联网 发布:经济学考研知乎 编辑:程序博客网 时间:2024/05/23 22:27

spring没有直接支持ehcache3,非常无奈,前2天学了ehcache3,现在整合不了,只好与net.sf.ehcache中的2.10.x版本整合,这两个版本的ehcache.xml文件语法格式差别挺大的,但是功能差不多。等过阵子再学习一下spring-Jcache-ehcache3的整合。


整合用到的类位于spring-context-support包下


spring整合ehchache2,对方法进行注解,第一次调用该方法时,执行方法并缓存返回值,再次调用该方法,若缓存没过期或没被删除,就不会执行方法,直接获取缓存中的返回值。流程图如下



先介绍一下注解的属性,属性中用到的#符号,其实是使用了SpEL(spring expression language)。


key:如果多个注解的key值一样,则共用同一个返回值(第一次调用某个方法返回的值),

一般使用方法参数的id等作为参数,避免key重复,#id就是spring el调用了方法参数id作为key。


value:缓存的名称,该缓存名必须先在ehcache.xml配置

cacheNames:与value一样


condition:符合条件的才会使用缓存,比如key="#id", condition = "#id > 10"


unless:与condition相反,不符合条件的才使用缓存


keyGenerator:指定我们自定义的key的生成策略的beanName,如果自定义类的类注解为@Component("customKeyGenerator"),那么keyGenerator = "customKeyGenerator"


cacheResolver:指定一个我们自定义的缓存解析器的beanName


beforeInvocation、allEntries:对所有entry进行操作,只适用@CacheEvict使用在removeAll方法的情况,默认都是false

注解介绍
@Cacheable(value="myCache",key="#id")
对方法的返回值进行缓存


@CachePut(value="myCache",key="#id")
更新缓存

@CacheEvict(value="myCache",allEntries=true,beforeInvocation=false)
删除缓存
beforeInvocation=true时,在调用方法前删除缓存,不管方法调用成功与否,
beforeInvocation=false时,只有方法调用成功才会删除缓存

@Caching
可以让一个方法同时使用多个注解,比如id小于10存在cache1中,大于10存在cache2中
@Caching(cacheable = {@Cacheable(value = "cache1", condition = "#id <10" ), 
@Cacheable(value = "cache2", condition = "#id >10" )})

@CacheConfig
类注解,定义类中多数方法使用相同的缓存名、缓存解析器等就可以使用该注解,
如果类中各个方法使用的缓存名等等不一样,那就没必要配置这个了。
方法注解中的属性会覆盖类注解中的属性。


整合的spring文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:cache="http://www.springframework.org/schema/cache"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/cache       http://www.springframework.org/schema/cache/spring-cache-3.2.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd">    <context:component-scan base-package="ehcacheAnnocationTest"/>    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">        <property name="configLocation" value="classpath:ehcache.xml"/>    </bean>    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">        <property name="cacheManager" ref="cacheManagerFactory"/>    </bean>    <!-- 启用缓存注解开关 -->    <cache:annotation-driven/>    <!-- 只针对cacheManger这个缓存管理器开启注解 -->    <!--<cache:annotation-driven cache-manager="cacheManager"/>-->    <!--cache-manager="cacheManager"--></beans>

ehcache.xml

<?xml version="1.0" encoding="utf-8" ?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="ehcache.xsd"         updateCheck="true" monitoring="autodetect" dynamicConfig="true">    <diskStore path="java.io.tmpdir"/>    <defaultCache            maxEntriesLocalHeap="1000"            eternal="false"            overflowToDisk="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            diskSpoolBufferSizeMB="30"            maxEntriesLocalDisk="1000000"            diskExpiryThreadIntervalSeconds="120"            memoryStoreEvictionPolicy="LRU">        <persistence strategy="localTempSwap"/>    </defaultCache>    <cache name="myCache"           maxEntriesLocalHeap="1000"           maxEntriesLocalDisk="100"           eternal="false"           diskSpoolBufferSizeMB="30"           timeToIdleSeconds="300"           timeToLiveSeconds="600"           memoryStoreEvictionPolicy="LFU"           transactionalMode="off">        <persistence strategy="localTempSwap"/>    </cache>    <cache name="test"           maxEntriesLocalHeap="1000"           maxEntriesLocalDisk="100"           eternal="false"           diskSpoolBufferSizeMB="30"           timeToIdleSeconds="300"           timeToLiveSeconds="600"           memoryStoreEvictionPolicy="LFU"           transactionalMode="off">        <persistence strategy="localTempSwap"/>    </cache></ehcache>

xsi:noNamespaceSchemaLocation="ehcache.xsd"
上面这一行的ehcache.xsd,我这边是没有找到,idea可以点File-settings-Language&Frameworks-Schemas and DTDs,右边界面,可以指定自己下载xsd文件,也可以忽略这个xsd文件校验。

测试Service类
package ehcacheAnnocationTest;import org.springframework.cache.annotation.*;import org.springframework.stereotype.Service;/** * writer: holien * Time: 2017-08-14 11:24 * Intent: 测试ehcache2整合spring的注解功能 */@Service@CacheConfig(cacheNames = "myCache")public class EhcacheAnnocationTest {    /**     * key:该缓存entry中的key     * value:     */    @Cacheable(key = "11")    public String getName() {        System.out.println("get Name By executing code");        return "pens";    }    @Cacheable(key = "11", condition = "11 > 10")    @Caching(put = {@CachePut, @CachePut}, evict = {@CacheEvict})    public String getName2() {        System.out.println("get Name By executing code");        return "haha";    }    // 特地用了名为test的cache,覆盖了类注解中的myCache    @Cacheable(cacheNames = "test", key = "11")    public int getAge() {        System.out.println("get Age By executing code");        return 24;    }    @CachePut()    public String updateName() {        System.out.println("update Name By executing code");        return "holien";    }    @CacheEvict    public void removeName() {        System.out.println("remove Name By executing code");    }}
我写了一个测试类来测试这几个注解,没有在控制台打印语句就证明只是取了缓存中的值,并没有执行方法

package ehcacheAnnocationTest;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * writer: holien * Time: 2017-08-14 22:22 * Intent: 调用缓存方法,测试是否进行缓存 */public class AppStart {    public static void main(String[] args) {        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext-ehcache.xml");        EhcacheAnnocationTest ehcacheAnnocationTest = applicationContext.getBean(EhcacheAnnocationTest.class);        // 第一次会在控制台打印语句,后面2次直接返回结果,不执行打印语句        System.out.println(ehcacheAnnocationTest.getName());        System.out.println(ehcacheAnnocationTest.getName());        System.out.println(ehcacheAnnocationTest.getName());        // 刷新缓存,会执行打印语句,后面一次直接返回更新后的结果        System.out.println(ehcacheAnnocationTest.updateName());        System.out.println(ehcacheAnnocationTest.getName());        // 删除缓存,会执行语句        ehcacheAnnocationTest.removeName();        // 删除后第一次又会在控制台打印语句        System.out.println(ehcacheAnnocationTest.getName());//        System.out.println(ehcacheAnnocationTest.getName());//        System.out.println(ehcacheAnnocationTest.getName());//        System.out.println(ehcacheAnnocationTest.getAge());//        System.out.println(ehcacheAnnocationTest.getAge());//        System.out.println(ehcacheAnnocationTest.getName());    }}
运行结果



快12点了,休息休息...



原创粉丝点击