Memcache+Spring AOP

来源:互联网 发布:sqlserver去重复查询 编辑:程序博客网 时间:2024/06/10 15:53
<aop:aspectj-autoproxy proxy-target-class='false'/>

proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。
如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。
如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。

package org.digdata.swustoj.aop.cache;import java.lang.reflect.Method;import java.util.List;import java.util.Map;import org.apache.log4j.Logger;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.digdata.swustoj.base.IMemCacheTemplate;import org.digdata.swustoj.model.CacheAccess;import org.digdata.swustoj.model.CacheFlush;import org.digdata.swustoj.util.ClassUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;/** *  * @author wwhhf * @since 2016年6月1日 * @comment 缓存切面管理 order值越小,顺序越高 cacheKey->className.methodName(args).version *          cacheValue->data versionKey->className.version cacheValue->Integer */@Order(2)@Aspect@Componentpublic class MemCacheAspect {    private static Logger logger = Logger.getLogger(MemCacheAspect.class);    private static final Class VERSION_KEY_TYPE = Long.class;    private static final String VERSION_SUFFIX = "version";    @Autowired    private IMemCacheTemplate iMemCacheTemplate = null;    /**     *      * @author wwhhf     * @since 2016年6月2日     * @comment 修改方法     */    @Pointcut("execution(* org.digdata.swustoj.mybatis.dao.impl.*.*(..)) "            + "|| execution(* org.digdata.swustoj.service.impl.*.*(..)) ")    public void methods() {    }    /**     *      * @author wwhhf     * @since 2016年6月1日     * @comment 先进行访问缓存,若命中则直接返回,否则继续执行方法     * @param joinpoint     * @throws Throwable     */    @Around("methods()")    public Object cacheAccess(ProceedingJoinPoint joinpoint) throws Throwable {        String clazzName = joinpoint.getTarget().getClass().getName();        String methodName = joinpoint.getSignature().getName();        Object[] args = joinpoint.getArgs();        Method method = ((MethodSignature) joinpoint.getSignature())                .getMethod();        boolean hasAnnotation = method.isAnnotationPresent(CacheAccess.class);        if (hasAnnotation) {// 存在需要缓存数据的注解            String version_key = getVersionKey(clazzName);// 获取缓存版本号的key            Long version_value = (Long) this.iMemCacheTemplate.getObject(                    version_key, VERSION_KEY_TYPE); // 获取缓存版本号            if (version_value == null) { // 版本号过期了,重新建立缓存版本号,该类以前的缓存全部过期                this.iMemCacheTemplate.set(version_key,                        version_value = getNextVersionValue());// 重新设置缓存版本号                System.out.println("缓存初始化: " + version_key + " -> " + version_value);                String cache_key = ClassUtil.getMethodInfo(clazzName,                        methodName, args, version_value);// 获得缓存的key                // ============================================                Object cache_value = joinpoint.proceed(args);// 缓存未命中                // ============================================                System.out.println("缓存未命中: " + cache_key);                this.iMemCacheTemplate.set(cache_key, cache_value);// 缓存数据                return cache_value;            } else {// 版本号未过期,查询该类此版本的缓存                CacheAccess annotation = method                        .getAnnotation(CacheAccess.class);// 获得注解                Class clazz = annotation.type(); // 获得json的class                String cache_key = ClassUtil.getMethodInfo(clazzName,                        methodName, args, version_value);// 获得cache_key                Object cache_value = null;                if (clazz == String.class) { // String                    cache_value = this.iMemCacheTemplate.getString(cache_key);                } else if (clazz == List.class) { // List                    Class subClazz = annotation.subType();                    cache_value = this.iMemCacheTemplate.getList(cache_key,                            subClazz);                } else if (clazz == Map.class) { // Map                    cache_value = this.iMemCacheTemplate.getMap(cache_key);                } else { // Object                    cache_value = this.iMemCacheTemplate.getObject(cache_key,                            clazz);                }                if (cache_value == null) { // 缓存未命中,需要缓存数据                    System.out.println("缓存未命中: " + cache_key);                    // ====================================                    cache_value = joinpoint.proceed(args);                    // ====================================                    this.iMemCacheTemplate.set(cache_key, cache_value);                } else { // 缓存命中                    System.out.println("缓存命中: " + cache_key);                }                return cache_value;            }        } else {// 不存在注解            return joinpoint.proceed(args);        }    }    /**     *      * @author wwhhf     * @since 2016年6月1日     * @comment 先进行缓存清除,再执行方法     * @param joinpoint     * @throws Throwable     */    @Around("methods()")    public Object cacheFlush(ProceedingJoinPoint joinpoint) throws Throwable {        String clazzName = joinpoint.getTarget().getClass().getName();        Object[] args = joinpoint.getArgs();        Method method = ((MethodSignature) joinpoint.getSignature())                .getMethod();        boolean hasAnnotation = method.isAnnotationPresent(CacheFlush.class);        if (hasAnnotation) {// 存在清除缓存的注解            improveVersion(clazzName);// 提高缓存的版本号        }        return joinpoint.proceed(args);    }    /**     * @author wwhhf     * @since 2016年6月5日     * @comment 提高相应类的版本     * @param clazzName     */    private void improveVersion(String clazzName) {        // 获取缓存版本号的key        String version_key = getVersionKey(clazzName);        // 获取缓存版本号        Long version = (Long) this.iMemCacheTemplate.getObject(version_key,                VERSION_KEY_TYPE);        if (version != null) {            // 版本号过期则不管,让查询统一处理            // 版本号未过期,提高版本号            this.iMemCacheTemplate.set(version_key,                    version = getNextVersionValue());            System.out.println("缓存版本提高: " + version_key + " -> " + version);        }    }    /**     *      * @author wwhhf     * @since 2016年6月2日     * @comment 获取类名对应的缓存版本号     * @param className     * @return     */    private String getVersionKey(String className) {        StringBuffer sb = new StringBuffer(className).append(".").append(                VERSION_SUFFIX);        return sb.toString();    }    /**     *      * @author wwhhf     * @since 2016年6月2日     * @comment 获取类名对应的下一次的缓存版本号(时间戳)     * @param className     * @return     */    private Long getNextVersionValue() {        return System.currentTimeMillis();    }}
package org.digdata.swustoj.model;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** *  * @author wwhhf * @since 2016年6月1日 * @comment 表示该方法需要先进行缓存清除,再执行该方法 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface CacheFlush {}
/**     *      * @author wwhhf     * @since 2016年5月26日     * @comment 条件查询标签     * @param search_ids     * @param search_name     * @param condition     * @param page     * @param rows     * @return     */    @CacheAccess(type = List.class, subType = Tags.class)    public List<Tags> selectTags(List<Integer> search_ids, String search_name,            String condition, Integer page, Integer rows);    /**     *      * @author wwhhf     * @since 2016年5月26日     * @comment 条件查询标签的数量     * @param search_ids     * @param search_name     * @param condition     * @param page     * @param rows     * @return     */    @CacheAccess(type = Integer.class)    public Integer selectTagsNum(List<Integer> search_ids, String search_name,            String condition);    /**     *      * @author wwhhf     * @since 2016年5月26日     * @comment 批量删除标签     * @param tids     * @return     */    @CacheFlush    public Boolean deleteTags(List<Integer> tids);    /**     *      * @author wwhhf     * @since 2016年5月26日     * @comment 添加标签     * @param record     * @return     */    @CacheFlush    public Boolean insertTags(Tags record);    /**     *      * @author wwhhf     * @since 2016年5月26日     * @comment 更新标签     * @param record     * @return     */    @CacheFlush    public Boolean updateTags(Tags record);

原先版本的缓存策略:Mybatis一级缓存+mysql自身缓存
现版本缓存策略:memcache+原版本
时间对比:
原:400多ms
现:160左右ms

不足

service层缓存建议不使用:service调用别的dao层的修改方法,一定要通过service层调用,否则会出现缓存同步问题。

0 0
原创粉丝点击