`

缓存方法 : Srping+Ehcache 在Service层配置缓存

 
阅读更多
自定义Key
package cn.com.voge.system.service;

import org.springframework.cache.interceptor.KeyGenerator;

import java.lang.reflect.Method;

/**
 * 项目名称: wp_idea_linux
 * 功能说明:
 * 创建者: Pandy,
 * 邮箱: panyongzheng@163.com, 1453261799@qq.com
 * 版权:
 * 官网:
 * 创建日期: 15-9-24.
 * 创建时间: 上午11:25.
 * 修改历史:
 * -----------------------------------------------
 */
public class RhKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object o, Method method, Object... objects) {
        return o.toString();
    }
}

<bean id="customGenerator" class="cn.com.voge.system.service.RhKeyGenerator">
<cache:annotation-driven cache-manager="cacheManager" key-generator="customGenerator" proxy-target-class="true"/>



@Cacheable 支持如下几个参数:
value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL
condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL


奇葩问题:
@Cacheable(value="h1m0Cache", key="#params.toString() + ',' + #sessionData.getInstanceId()")
public ControllerContext setDropDownData(ArrayList<Map<String, Object>> params, SessionData sessionData,final String cacheKey) {
}

, 在开发环境下没问题,但是打包之后就出现问题 Method call: Attempted to call method toString() on null context object
=====================>一直找不到问题原因,params参数不可能是null, 难道不能使用方法里面的参数来做key? http://hanqunfeng.iteye.com/blog/1158824, 这个文章已经推翻了, 可是为什么出现问题呢?


SpringMVC整合Ehcache(注解方式): http://blog.csdn.net/jadyer/article/details/12257865,介绍很详细.
注释驱动的 Spring cache 缓存介绍 https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/, 里面介绍了注解和配置.

@CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存
@CacheEvict 即应用到移除数据的方法上,如删除方法,调用方法时会从缓存中移除相应的数据
@Cacheable 应用到读取数据的方法上,即可缓存的方法,如查找方法:先从缓存中读取,如果没有再调用方法获取数据,然后把数据添加到缓存中



@Cacheable 注释,则当重复使用相同参数调用方法的时候,方法本身不会被调用执行,即方法本身被略过了,取而代之的是方法的结果直接从缓存中找到并返回了。
@Cacheable(value="accountCache"): 使用accountCache缓存.
@CacheEvict(value=”accountCache”,key=”#account.getName()”),其中的 Key 是用来指定缓存的 key 的,这里因为我们保存的时候用的是 account 对象的 name 字段,所以这里还需要从参数 account 对象中获取 name 的值来作为 key,前面的 # 号代表这是一个 SpEL 表达式,此表达式可以遍历方法的参数对象,具体语法可以参考 Spring 的相关文档手册。
@Cacheable(value="accountCache",condition="#userName.length() <= 4") condition=”#userName.length() <=4”,这里使用了 SpEL 表达式访问了参数 userName 对象的 length() 方法,条件表达式返回一个布尔值,true/false,当条件为 true,则进行缓存操作,否则直接调用方法执行的返回结果。
@Cacheable(value="accountCache",key="#userName.concat(#password)")  key 属性,其中引用了方法的两个参数 userName 和 password

@CachePut 注释,这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中。现实中并不总是如此,有些情况下我们希望方法一定会被调用,因为其除了返回一个结果,还做了其他事情,例如记录日志,调用接口等,这个时候,我们可以用 @CachePut 注释
@Cacheable(value="accountCache")// 使用了一个缓存名叫 accountCache 
 public Account getAccountByName(String userName) { 
   // 方法内部实现不考虑缓存逻辑,直接实现业务
   return getFromDB(userName); 
 } 
 @CachePut(value="accountCache",key="#account.getName()")// 更新 accountCache 缓存
 public Account updateAccount(Account account) { 
   return updateDB(account); 
 } 
 private Account updateDB(Account account) { 
   System.out.println("real updating db..."+account.getName()); 
   return account; 
 }


注解碰到的问题:
Cannot find cache named xxxxxx CacheableOperation http://m.bianceng.cn/Programming/Java/201309/37363_10.htm
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="classpath:ehcache.xml"/>
	</bean>
	<bean id="cacheManager1" class="org.springframework.cache.ehcache.EhCacheCacheManager">
		<property name="cacheManager" ref="cacheManagerFactory"/>
	</bean>
	<bean id="cacheManager"
		  class="org.springframework.cache.support.CompositeCacheManager">
		<property name="cacheManagers">
			<list>
				<ref bean="cacheManager1" />
			</list>
		</property>
		<property name="fallbackToNoOpCache" value="true" />
	</bean>
	<cache:annotation-driven cache-manager="cacheManager"/>

在找不到 accountCache,且没有将 fallbackToNoOpCache 设置为 true 的情况下,系统会抛出异常。



原文: http://miaoxianjie.iteye.com/blog/1700379
有些地方做了适当修改
1. ehcache 文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  
  
    <diskStore path="java.io.tmpdir"/>  
    <defaultCache  
            maxElementsInMemory="10000"  
            eternal="false"  
            timeToIdleSeconds="520"  
            timeToLiveSeconds="520"  
            overflowToDisk="true"  
            maxElementsOnDisk="10000000"  
            diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120"  
            memoryStoreEvictionPolicy="LRU"  
     />  
  
       
    <cache name="testServiceCache"  
            maxElementsInMemory="10"  
            eternal="false"  
            timeToIdleSeconds="200"  
            timeToLiveSeconds="300"  
            overflowToDisk="true"  
            />      
              
</ehcache>  


2. applicationContext.xml 文件 相关代码
   <!-- Service Cache   Ehcache -->  
        
   <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
    <property name="configLocation">    
        <value>classpath:ehcache.xml</value>    
        </property>   
   </bean>  
  
   <bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
       <property name="cacheManager">  
           <ref local="cacheManager"/>  
       </property>  
       <property name="cacheName">  
           <value>testServiceCache</value>  
       </property>  
   </bean>  
     
<!-- methodCacheInterceptor 要自己实现的代码 -->  
   <bean id="methodCacheInterceptor" class="com.miao.service.MethodCacheInterceptor">  
       <property name="cache">  
           <ref local="methodCache"/>  
       </property>  
   </bean>  
     
   <!-- 配置要拦截的service, 拦截service包下所有类的所有方法  -->  
   <aop:config>  
    <aop:pointcut id="methodCachePointCut" expression="execution(* com.miao.service.*.*(..))" />  
    <aop:advisor pointcut-ref="methodCachePointCut" advice-ref="methodCacheInterceptor" />  
</aop:config>  
     
<!--  也可用此种方式 指定哪些方法使用cache-->  
   <!--   
   <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
       <property name="advice">  
           <ref local="methodCacheInterceptor"/>  
       </property>  
       <property name="patterns">  
           <list>  
               <value>.*getStepPartKitList</value>  
           </list>  
       </property>  
   </bean>  
-->  


3.MethodCacheInterceptor
package cn.com.voge.system.interceptor;

import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.InitializingBean;

import java.io.Serializable;

/**
 * 项目名称: wp_idea_linux
 * 功能说明:
 * 创建者: Pandy,
 * 邮箱: panyongzheng@163.com, 1453261799@qq.com
 * 版权:
 * 官网:
 * 创建日期: 15-9-16.
 * 创建时间: 下午4:31.
 * 修改历史:
 * -----------------------------------------------
 */
public class MethodCacheInterceptor implements MethodInterceptor,InitializingBean {
    //private static final Log LOGGER = LogFactory.getLog(MethodCacheInterceptor.class);

    private Ehcache cache;//我使用的Spring版本使用Ehcache类,一些可能是使用Cache类.注意一下.

    public void setCache(Ehcache cache) {
        this.cache = cache;
    }


    public Object invoke(MethodInvocation invocation) throws Throwable {

        String targetName = invocation.getThis().getClass().getName();
        String methodName = invocation.getMethod().getName();
        Object[] arguments = invocation.getArguments();
        Object result;

        String cacheKey = getCacheKey(targetName, methodName, arguments);
        Element element = cache.get(cacheKey);
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        if (element == null) {
            result = invocation.proceed();   //调用被拦截的目标方法
            //LOGGER.info("Set into Cache");
            element = new Element(cacheKey, (Serializable) result);
            cache.put(element);
        }
        return element.getValue();
    }


    private String getCacheKey(String targetName, String methodName,Object[] arguments) {
        StringBuffer sb = new StringBuffer();
        //拼cacheKey 这里使用 className.methodName(arg1,arg2.....argN) 作为key
        sb.append(targetName).append(".").append(methodName).append("(");
        if ((arguments != null) && (arguments.length != 0)) {
            for (int i = 0; i < arguments.length; i++) {
                sb.append(arguments[i]);
                if (i + 1 != arguments.length) {
                    sb.append(",");
                }
            }
        }
        sb.append(")");
        return sb.toString();
    }

    public void afterPropertiesSet() throws Exception {
        if(null == cache) {
            throw new IllegalArgumentException("Cache should not be null.");
        }
    }

}

 

4.使用Junit测试即可,传递相同的参数,调用service内的同一个方法,只会进入DAO一次
分享到:
评论

相关推荐

    spring + ehcache + redis两级缓存

    在缓存管理方面,Spring 提供了 Spring Cache抽象层,可以方便地集成各种缓存实现,如Ehcache、Hazelcast或Redis。 **Ehcache** 是一个广泛使用的Java缓存库,适合在内存中存储数据。它提供了一种快速访问最近使用...

    Ehcache(一): Spring + Ehcache开场白

    配置Ehcache,我们可以在Spring的配置文件中定义一个`CacheManager` bean,指定Ehcache的配置文件路径。Ehcache的配置文件(如ehcache.xml)包含了缓存的命名空间、大小限制、过期策略等信息。例如: ```xml ...

    spring+ehcache示例整合Demo

    然后,我们需要在服务层或者DAO层的类中使用`@Cacheable`注解来标记需要缓存的方法。这个注解告诉Spring在调用该方法时,先检查缓存中是否存在结果,如果存在则直接返回,不存在则执行方法并将结果放入缓存: ```...

    Struts2+Spring+Hibernate+Ehcache+AJAX+JQuery+Oracle 框架集成用户登录注册Demo工程

    1)Demo 学习要点简介: ...2.Eclipse 导入后可能需要在 Xml Catalog 手动添加:ehcache-spring-1.2.xsd(ehcache-spring-annotations-1.2.0-sources.jar里面有,自己找下)。 3.内附Oracle建表等可执行语句。

    Spring+EhCache缓存实例

    **Spring+EhCache缓存实例详解** 在现代的Java企业级应用中,缓存技术扮演着至关重要的角色,它能够显著提升系统性能,减少数据库负载。Spring框架与EhCache的结合,为开发者提供了一种高效、易用的缓存解决方案。...

    Spring+Ehcache集成

    本篇文章将详细介绍如何在Spring项目中集成Ehcache,以及如何通过Spring的AOP(面向切面编程)实现方法级别的缓存注解。 首先,我们需要在项目中引入Ehcache的依赖。通常,这可以通过在`pom.xml`文件中添加Maven...

    spring+ehcache demo

    总结,这个"spring+ehcache demo"是一个全面的示例,涵盖了从引入Ehcache依赖、配置Spring Cache到编写缓存注解的方法。通过学习和实践这个示例,开发者可以深入了解Spring与Ehcache的集成,以及如何利用缓存提升...

    Spring+SpringMVC+Ehcache+Shiro+BootStrap企业级开发平台

    【B1】Spring+SpringMVC+Ehcache+Shiro+BootStrap企业级开发平台源码下载 内置功能 用户管理 角色管理 菜单管理 字典管理 部门管理 附件管理 参数管理 连接池监视 日志管理 技术选型 1、后端 核心框架...

    jar包整合:Springmvc+hibernate+Ehcache+shior+mysql+Oracle+fastjson

    在Java应用中,Ehcache用于存储频繁访问的数据,减少数据库的访问压力,提供缓存管理策略,如LRU(最近最少使用)算法。 4. **Shiro**:Apache Shiro是一个安全管理框架,它负责身份认证、授权(权限控制)、会话...

    Spring + Ehcache 注解形式配置

    总结来说,通过在Spring中使用Ehcache的注解配置,我们可以轻松地实现缓存管理,提高应用性能。在实际开发中,还需要根据具体需求调整缓存策略,如设置不同的缓存区域、过期策略等,以达到最佳效果。同时,需要注意...

    Spring+Hibernate+ehcache整合

    1. **Spring配置**:Spring的配置文件(如`applicationContext.xml`)会定义bean,包括数据源、SessionFactory(Hibernate)、缓存管理器(Ehcache)以及业务层和服务层的组件。通过依赖注入,Spring将这些组件装配...

    spring+ibatis+ehcache整合例子

    Ehcache的配置包括在Spring配置文件中声明CacheManager,以及定义需要缓存的bean和对应的缓存策略。 4. **编写Mapper接口和XML映射文件** iBatis中的Mapper接口对应数据库操作,XML映射文件定义了SQL语句和结果...

    spring+ehcache完整示例demo

    在IT行业中,Spring框架是Java领域最常用的轻量级应用框架之一,而Ehcache则是一种广泛使用的内存缓存系统,常与Spring搭配用于提升应用性能。本示例旨在通过一个完整的Spring集成Ehcache的Demo,帮助开发者理解如何...

    Spring AOP+ehCache简单缓存系统解决方案

    首先,我们要明确需求:我们需要在Service或DAO层的get/find等查询方法中缓存返回结果,当数据通过Create/update/delete方法被修改时,必须及时刷新缓存中的相应内容。为了满足这些需求,我们可以利用Spring AOP的...

    maven+spring+ehcache

    在Spring应用中,Ehcache可以通过Spring的缓存抽象进行集成,以便在需要时自动缓存结果。 **Spring JDBC** 提供了一个抽象层,简化了与数据库的交互。它提供模板类如JdbcTemplate,用于执行SQL查询和更新操作,减少...

    Spring 与Ehcache实现基于方法的缓存

    本篇文章将详细探讨如何在Spring框架中集成并实现基于方法的缓存机制,利用Ehcache来优化数据访问。 首先,我们需要理解Spring的AOP概念,AOP允许我们定义横切关注点,如日志、事务管理或,正如在这个案例中,缓存...

    SpringMVC+Mybatis+Spring+Shiro+ehcache整合配置文件

    Ehcache可以很好地与Spring集成,通过简单的配置即可实现缓存管理。 在整合这些技术时,首先需要在Spring的配置文件中定义bean,包括数据源、SqlSessionFactory(Mybatis的核心)、MapperScannerConfigurer(扫描...

    Spring+Struts+页面缓存+内存数据库+licence+proxool+EhCache 搭建的系统基础平台

    "Spring+Struts+页面缓存+内存数据库+licence+proxool+EhCache" 的组合提供了一个强大的系统基础架构,便于快速开发和部署。接下来,我们将深入探讨这些组件及其在J2EE中的作用。 首先,Spring框架是Java应用的核心...

    spring+ehcache

    - 配置Spring:在Spring配置文件中启用缓存管理器,并指定使用Ehcache。 - 使用注解:在需要缓存的方法上添加`@Cacheable`、`@CacheEvict`等注解。 **二、Spring Cache注解** 1. **@Cacheable** 此注解用于标记...

    spring MVC+ibatis+ehcache开发包集合

    自己项目的开发包集合,其中包括:缓存处理ehcache相关jar,spring MVC4.0 jar,ehcache依赖jar,以及其他jar(图像处理thumbnailator-0.4.2),包虽然不是很新但可用。实际使用时找包较为麻烦,现在整理出来,希望...

Global site tag (gtag.js) - Google Analytics