EHCache作为一种通用缓存解决方案集成进 Spring。
我将示范拦截器的例子,它能把方法返回的结果缓存起来。
利用 Spring IoC 配置 EHCache
在 Spring 里配置 EHCache 很简单。你只需一个 ehcache.xml 文件,该文件用于配置 EHCache:
拦截器将使用 ”constantSeviceCache” 区域缓存方法返回结果。下面利用 Spring IoC 让 bean 来访问这一区域。
可以灵活的根据缓存的时间来建立多个这样的缓存,来控制不同的缓存时间
构建我们的 MethodCacheInterceptor
该拦截器根据spring2.0规范。一旦运行起来(kicks-in),它首先检查被拦截方法是否被配置为可缓存的。这将可选择性的配置想要缓存的 bean 方法。只要调用的方法配置为可缓存,拦截器将为该方法生成 cache key 并检查该方法返回的结果是否已缓存。如果已缓存,就返回缓存的结果,否则再次调用被拦截方法,并缓存结果供下次调用。
com.heshen.cache.MethodCacheInterceptor
MethodCacheInterceptor 代码说明了:
- 默认条件下,所有方法返回结果都被缓存了(methodNames 是 null)
- 缓存区利用 IoC 形成
- cacheKey 的生成还包括方法参数的因素(译注:参数的改变会影响 cacheKey)
使用 MethodCacheInterceptor
下面摘录了怎样配置 MethodCacheInterceptor:
译注
夏昕所著《Hibernate 开发指南》,其中他这样描述 EHCache 配置文件的:
ehcache.xml 文件
<ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" //Cache中最大允许保存的数据数量 eternal="false" //Cache中数据是否为常量 timeToIdleSeconds="120" //缓存数据钝化时间 timeToLiveSeconds="120" //缓存数据的生存时间 overflowToDisk="true" //内存不足时,是否启用磁盘缓存 /> </ehcache> <cache name="constantSeviceCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600" overflowToDisk="true" />
|
提供缓存拦截的类
MethodCacheInterceptor.java
/** */ package com.heshen.cache;
import java.io.Serializable; import java.lang.reflect.Method;
import net.sf.ehcache.Cache; import net.sf.ehcache.Element;
import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert;
/** * 针对方法切入,进行缓存的拦截器 * @author wanggang @version 2010-12-03 * * 缓存处理 */ public class MethodCacheInterceptor implements InitializingBean {
private Logger logger = Logger.getLogger("Method-Cache-Inegceptor");
private Cache serviceCache;
/** * 设置缓存名 */ public void setServiceCache(Cache serviceCache) { this.serviceCache = serviceCache; }
/** * 主方法 如果某方法可被缓存就缓存其结果 方法结果必须是可序列化的(serializable) */ public Object doCacheOperation(ProceedingJoinPoint pjp) throws Throwable {
String targetName = pjp.getTarget().getClass().getName(); Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod();
// String methodName = pjp.getThis()methodName. // invocation.getMethod().getName(); String methodName = method.getName();
Object[] arguments = pjp.getArgs();// invocation.getArguments(); Object result; // logger.info("looking for method result in cache"); String cacheKey = getCacheKey(targetName, methodName, arguments); logger.info("cache key" + cacheKey); Element element = serviceCache.get(cacheKey); if (element == null) { // call target/sub-interceptor logger.info("calling intercepted method"); result = pjp.proceed();
// cache method result logger.info("caching result"); element = new Element(cacheKey, (Serializable) result); serviceCache.put(element); } return element.getValue();
}
/** * creates cache key: targetName.methodName.argument0.argument1... */ private String getCacheKey(String targetName, String methodName, Object[] arguments) throws Exception { StringBuffer sb = new StringBuffer(); sb.append(targetName).append(".").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sb.append(".").append(arguments[i]); } } return sb.toString(); } /** * 检查是否提供必要参数。 */ public void afterPropertiesSet() throws Exception { Assert.notNull(serviceCache, "A cache is required. Use setCache(Cache) to provide one."); }
}
|
cacheInterceptor.xml缓存拦截器配置文件
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" default-autowire="byName"> <!-- 实际提供缓存服务的类 --> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/> <!-- 缓存不会变动的服务 --> <bean id="constantSeviceCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref bean="cacheManager"/> </property> <property name="cacheName"> <value>constantSeviceCache</value> </property> </bean>
<!-- 缓存不会变动的服务 --> <bean id="constantSeviceCacheMethodCacheInterceptor" class="com.heshen.cache.MethodCacheInterceptor"> <property name="serviceCache"> <ref local="constantSeviceCache" /> </property> </bean> <!-- 缓存不会变动的服务 --> <aop:config> <aop:aspect id="constantSeviceCacheOperation" ref="constantSeviceCacheMethodCacheInterceptor"> <aop:pointcut id="test1ConstantSeviceCacheCut" expression="execution(* com.heshen.service.impl.Test1ServiceImpl.*(..))"/> <aop:pointcut id="test2ClassServiceCacheCut" expression="execution(* com.heshen.service.impl.Test2ServiceImpl.*(..))"/> <aop:around pointcut-ref="test1ConstantSeviceCacheCut" method="doCacheOperation"/> <aop:around pointcut-ref="test2ClassServiceCacheCut" method="doCacheOperation"/> </aop:aspect> </aop:config>
<!-- 还可以继续配置其他的缓存切面 --> <!-- <aop:config> <aop:aspect id="constantSeviceCacheOperation" ref="constantSeviceCacheMethodCacheInterceptor"> <aop:pointcut id="test1ConstantSeviceCacheCut" expression="execution(* com.heshen.service.impl.Test1ServiceImpl.*(..))"/> <aop:pointcut id="test2ClassServiceCacheCut" expression="execution(* com.heshen.service.impl.Test2ServiceImpl.*(..))"/> <aop:around pointcut-ref="test1ConstantSeviceCacheCut" method="doCacheOperation"/> <aop:around pointcut-ref="test2ClassServiceCacheCut" method="doCacheOperation"/> </aop:aspect> </aop:config>--> </beans>
|
cacheInterceptor.xml缓存拦截器配置文件
/** */ com.heshen.service.impl;
/** * 具体的service类 * @author wanggang @version 2010-12-03 * * 缓存处理 */ public class Test2ServiceImpl implements test2Service {
private Logger logger = Logger.getLogger("Test2ServiceImpl ");
public void doSomeThing1(String a){ }
public String doSomeThing2(String arg1,String arg2){ } .... }
|
分享到:
相关推荐
spring ioc容器初始化流程图 spring ioc容器依赖注入流程图 spring aop实现原理流程图
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...
spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...
SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找...
主要为大家详细解析了Spring中IoC优点与缺点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
以注解方式模拟Spring IoC AOP,了解Spring是如何实现的.
spring Ioc容器配置 IOC容器数据源配置 <!-- 配置数据源 --> destroy-method="close"> <value>org.gjt.mm.mysql.Driver <value>jdbc:mysql://localhost:3306/demo <value>root ...
SpringIOC和AOP实现机制模拟,来自与网络。
详细讲解了springioc的各种注入方式以及对应的java方式。讲解了springioc和DI的区别,以及注入特殊复杂的属性
Spring ioc Spring ioc
spring ioc思维导图,让自己快速、详尽地了解spring ioc知识。
个人整理SpringIOC源码解读,望大婶们指点指点,后续继续添加
spring基础Spring IOC和Spring AOP的原理及使用
Spring IoC加载流程讲解以及IoC思想和依赖倒置原则
这是个模拟spring ioc的学习例子,是个java工程。有助于对aop和ioc的理解
SpringIOC经典Demo,绝对的经典.
Spring Ioc 注解 依赖注入
spring的ioc容器详细讲解,理解springioc容器