SSM的项目结构

image

simple-spring-memcached本质上是采用了AOP的方式来实现缓存的调用和管理

aop : Advice 的实现

api: ssm 提供了很多的advice。如:readThroughSingleCache、readThroughMultiCache、readThroughAssignCache 等等。

      提供给应用程序调用。当当遇到相应的切入点时,会执行这些Advice来对memcached加以管理。

config:memcached 的服务器配置地址

mapper:

providers:memcached 的两个客户端实现类。spymemcached和xmemcached

transcoders : json 的一些转换类

util: 工具包

test:自己写的测试类,SSM项目没有的

@readThroughSingleCache 的实现

@readThroughSingleCache 用户获取缓存,在应用程序中是经常用到的。

它的实现方法如下:

/**
     * readThroughSingleCache 的实现
     * @param pjp
     * @return
     * @throws Throwable
     */
    protected Object cache(final ProceedingJoinPoint pjp) throws Throwable {
        if (isDisabled()) {
            getLogger().info("Cache disabled");
            // 这里如果关闭了ssm.cache.disable ,那就直接执行目标方法
            return pjp.proceed();
        }
        // This is injected caching. If anything goes wrong in the caching, LOG
        // the crap outta it, but do not let it surface up past the AOP injection itself.
        final T annotation;
        final AnnotationData data;
        final Class<?> jsonClass;
        String cacheKey = null;
        try {
            // getMethodToCache 这个就是拿到需要缓存的方法。在判断是否是目标方法时,它通过方法的名称和参数进行匹对,
            // 如果是泛型方法,还通过了桥接方法获取得到目标方法。
            final Method methodToCache = getCacheBase().getMethodToCache(pjp);
            // 校验 methodToCache 的返回值是否是void ,如果是抛出异常。
            getCacheBase().verifyReturnTypeIsNoVoid(methodToCache, annotationClass);
            annotation = methodToCache.getAnnotation(annotationClass);
            jsonClass = getCacheBase().getReturnJsonClass(methodToCache);
            // 获取到目标方法的一些参数:命名空间、失效的时间等等。
            data = AnnotationDataBuilder.buildAnnotationData(annotation, annotationClass, methodToCache);

            //得到cacheKey 
            cacheKey = getCacheKey(data, pjp.getArgs(), methodToCache.toString());

            final Object result = getCacheBase().getCache(data).get(cacheKey, jsonClass);
            // 成功命中cache
            if (result != null) {
                getLogger().debug("Cache hit.");
                return getCacheBase().getResult(result);
            }
        } catch (Throwable ex) {
            getLogger()
                    .warn(String.format("Caching on method %s and key [%s] aborted due to an error.", pjp.toShortString(), cacheKey), ex);
            return pjp.proceed();
        }

        final Object result = pjp.proceed();

        // This is injected caching. If anything goes wrong in the caching, LOG
        // the crap outta it, but do not let it surface up past the AOP injection itself.
        try {
            // 这里是没有缓存的情况,然后根据缓存的key ,过期时间等等,设置缓存
            final Object submission = getCacheBase().getSubmission(result);
            getCacheBase().getCache(data).set(cacheKey, data.getExpiration(), submission, jsonClass);
        } catch (Throwable ex) {
            getLogger()
                    .warn(String.format("Caching on method %s and key [%s] aborted due to an error.", pjp.toShortString(), cacheKey), ex);
        }
        return result;
    }
原文地址:https://www.cnblogs.com/pan2011/p/3650290.html