@Repository
public interface UserMapper {
public abstract List<User> select();
}
static void testEhcache3(UserService userService){
testPage(userService);
userService.findUsers();
testPage(userService);// ����sql
userService.findUsers(); //使用了缓存,没有打印sql
}
MethodCacheInterceptor的invoke方法没有执行
切点表达式错误:
<value>cn.mapper.UserMapper.find*</value>
10:04:50,687 INFO cn.web.interceptor.MethodCacheInterceptor - com.sun.proxy.$Proxy23.select使用缓存:mobileCache
<!-- Ehcache与spring整合 -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true">
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
<!-- 这里的方法拦截器主要是对你要拦截的类的方法进行拦截,然后判断该方法的类路径+方法名称+参数值组合的cache key在缓存cache中是否存在。如果存在就从缓存中取出该对象,转换成我们要的返回类型。没有的话就把该方法返回的对象添加到缓存中即可。值得主意的是当前方法的参数和返回值的对象类型需要序列化。-->
<!-- 配置一个简单的缓存工厂bean对象 -->
<bean id="simpleCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="ehCacheManager" />
<!-- 使用缓存 关联ehcache.xml中的缓存配置 -->
<property name="cacheName" value="mobileCache" />
</bean>
<!-- 配置一个缓存拦截器对象,处理具体的缓存业务 -->
<bean id="methodCacheInterceptor" class="cn.web.interceptor.MethodCacheInterceptor">
<property name="cache" ref="simpleCache"/>
</bean>
<!-- 参与缓存的切入点对象 (切入点对象,确定何时何地调用拦截器) -->
<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 配置缓存aop切面 -->
<property name="advice" ref="methodCacheInterceptor" />
<!-- 配置哪些方法参与缓存策略 -->
<!-- .表示符合任何单一字元 ### +表示符合前一个字元一次或多次 ### *表示符合前一个字元零次或多次 ### \Escape任何Regular expression使用到的符号 -->
<!-- .*表示前面的前缀(包括包名) 表示print方法-->
<property name="patterns">
<list>
<!-- <value>cn.service.impl.*UserService*\.*find*</value> -->
<!-- <value>cn.service.impl.*UserService*\.*select.*</value> -->
<value>cn.mapper.UserMapper.find*</value>
<value>cn.mapper.UserMapper.select*</value>
<value>cn.mapper.UserMapper.count</value>
</list>
</property>
</bean>
在ehcache.xml中添加如下cache配置
<cache name="mobileCache"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LFU" />
import java.io.Serializable;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* 缓存方法拦截器<br>
* 参考地址:http://www.cnblogs.com/hoojo/archive/2012/07/12/2587556.html
*/
public class MethodCacheInterceptor implements MethodInterceptor,
InitializingBean {
private Logger log = LoggerFactory.getLogger(MethodCacheInterceptor.class);
private Cache cache;
public MethodCacheInterceptor() {
super();
}
public void setCache(Cache cache) {
this.cache = cache;
}
/**
* 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值,<br>
* 否则,返回数据库查询结果,并将查询结果放入cache
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
// 这个表示哪个类调用(或触发)了这个MethodCacheInterceptor。例如:com.cache.service.UserServiceImpl
String targetName = invocation.getThis().getClass().getName();
// 这个表示哪个方法触发了这个类(MethodCacheInterceptor)方法(invoke)的调用,例如:getAllUser
String methodName = invocation.getMethod().getName();
// 方法调用的参数
Object[] arguments = invocation.getArguments();
Object result;
String cacheKey = this.getCacheKey(targetName, methodName, arguments);
Element element = null;
synchronized (this) {
element = cache.get(cacheKey);
if (element == null) {
log.info(cacheKey + "加入到缓存:" + cache.getName());
// 调用实际的方法
result = invocation.proceed();
element = new Element(cacheKey, (Serializable) result);
cache.put(element);//放入cache中
} else {
log.info(cacheKey + "使用缓存:" + cache.getName());
}
}
log.info("*************************interceptor*************");
return element.getObjectValue();
}
/**
* 返回具体的方法全路径名称、参数<br>
* cache key包括包名+类名+方法名,例如:com.cache.service.UserServiceImpl.getAllUser
*
* @param targetName
* 全路径
* @param methodName
* 方法名称
* @param arguments
* 参数
* @return 完整方法名称
*/
private String getCacheKey(String targetName, String methodName,
Object[] arguments) {
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 {
if (null == cache) {
throw new IllegalArgumentException("Cache should not be null.");
}
}
}