使用aop实现系统的缓存谋略

使用aop实现系统的缓存策略

通过AOP改善项目中缓存策略

最近项目中要添加memcached来改善系统的访问速度

memcached是个很好用的缓存系统,也很好搭建和维护,这里就不做介绍

下面主要介绍一下怎么来在项目中添加memcached

现在想起来的有两种方式添加

1、在需要添加memcached的方法中都显示的添加和memcached有关的方法

2、使用aop的方式来添加memcached的策略

两个方法的优缺点:

方法一:

优点:直观,明确,让人一下就能看到缓存的存在

缺点:代码编写量比较大。修改起来比较痛苦,比如那一天换缓存的实现方式或者不使用缓存了,需要修改很多方法

方法二:

优点:代码量少,易于维护

缺点:不够直观。并且由于是方法都是以前存在的,也需要修改以前的代码,让他们符合一定的规律,这样才能统一处理

下面主要讲一讲通过AOP方式实现缓存的策略

思路如下:

1aop处理缓存,得区分出来被代理的方法哪些是更新、添加、删除、查询的方法

更新和添加方法的话,直接调用set方法进行更新

删除方法的时候,调用delete方法进行删除

查询方法,查看是否有缓存,如果没有的话,从数据库中查询到,然后添加到缓存中

2、把以前的方法进行分类,那些方法的查询可以继承一个查询父类(该查询父类可以拿到关键的查询条件),那些方法能继承统一的修改父类(修改父类也能拿到关键的查询条件)。其中查询条件作为关键key来存入到缓存中

具体实现可以查看源代码,代码已经上传

主要实现代码如下:

1、CacheUserAop

 针对第一个参数为user对象的操作缓存的aop

写道
package com.wangcanpei.aop;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;

import com.wangcanpei.model.User;
import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;

/**
* 针对第一个参数为user对象的操作缓存的aop
* @author wangcanpei
*
*/
public class CacheUserAop {
private static final Log log=LogFactory.getLog(CacheUserAop.class);


/**
* 在新增数据的时候,调用的aop,作用是往缓存中新增数据
* @param point
* @return
*/
public Object addCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.set(key, user);
} catch (Throwable e) {
log.error(e);
}
return ret;
}

/**
* 在删除数据的时候,调用的aop,作用是删除缓存里的数据
* @param point
* @return
*/
public Object delCacheAfter(JoinPoint point){
Object ret=null;
User user=(User)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(user);
log.error("key:"+key);
MemcachedClientUtil.delete(key);
} catch (Throwable e) {
log.error(e);
}
return ret;
}

/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(User user){
String key="aopTest";
key=key+"&"+user.getName();
return MD5.getMD5(key);
}
}

 2、SelectCacheAop 针对第一个参数为String的查询aop

写道
package com.wangcanpei.aop;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import com.wangcanpei.util.MD5;
import com.wangcanpei.util.MemcachedClientUtil;

/**
* 针对第一个参数为String的查询aop
* @author wangcanpei
*
*/
public class SelectCacheAop {
private static final Log log=LogFactory.getLog(SelectCacheAop.class);


/**
* 在查询数据的时候使用,并且第一个参数就是查询条件的
* @param point
* @return
*/
public Object select(ProceedingJoinPoint point){
Object ret=null;
String name=(String)point.getArgs()[0];
//判断是否添加成功了,如果添加成功,把该值也添加到缓存中
try {
String key=getKey(point,name);
log.error("key:"+key);

Object obj=MemcachedClientUtil.get(key);
if(null!=obj){
return obj;
}

return point.proceed();

} catch (Throwable e) {
log.error(e);
}
return ret;
}


/**
* 缓存中key的定义规则是:aopTest+参数值,转换成md5
* @param point
* @param user
* @return
*/
private String getKey(JoinPoint point,String name){
String key="aopTest";
key=key+"&"+name;
return MD5.getMD5(key);
}
}

 配置文件

写道
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<bean id="cacheUserAop" class="com.wangcanpei.aop.CacheUserAop" />
<bean id="selectCacheAop" class="com.wangcanpei.aop.SelectCacheAop" />
<aop:config>
<aop:aspect id="TestAspect" ref="cacheUserAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->
<aop:pointcut id="userAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="userAop" method="addCacheAfter"/>
<aop:pointcut id="deleteuserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(com.wangcanpei.model.User,..))" />
<aop:after-returning pointcut-ref="deleteuserAop" method="delCacheAfter"/>

</aop:aspect>

<aop:aspect id="selectAspect" ref="selectCacheAop">
<!--配置com.wangcanpei.service包下所有类或接口的所有方法-->

<aop:pointcut id="seluserAop"
expression="execution(* com.wangcanpei.service.impl.*.*(String,..))" />
<aop:around pointcut-ref="seluserAop" method="select"/>

</aop:aspect>
</aop:config>



</beans>