Spring AOP+自定义注解实现缓存

Spring AOP配置:

<aop:config>
	<aop:aspect ref="cacheAdvice">
		<aop:pointcut id="cachePointcut" expression="execution(* cn.vobile.service..*.*(..)) and @annotation(cacheable)"/>
		<aop:around method="cacheData" pointcut-ref="cachePointcut"/>
	</aop:aspect>
</aop:config>

<bean id="cacheAdvice" class="cn.vobile.common.cache.aop.CacheAdvice">
<property name="cache" ref="localCache"/>
</bean>

自定义注解Cacheable代码如下:

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {

    /**
     * The cache key.
     *
     * @return
     */
    String key() default "";

    /**
     * The cache timeout, unit for minute.
     *
     * @return
     */
    int timeout() default 30;

    /**
     * Whether serialize the cache object.
     *
     * @return
     */
    boolean serialize() default false;

}

切面处理类(CacheAdvice)及其父类(CacheAdviceSupport)代码如下:

public class CacheAdvice extends CacheAdviceSupport {

    public Object cacheData(ProceedingJoinPoint joinPoint, Cacheable cacheable) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = AopUtils.getMostSpecificMethod(methodSignature.getMethod(), joinPoint.getTarget().getClass());

        CacheOperationContext context = getOperationContext(targetMethod, joinPoint.getArgs(), joinPoint.getTarget(), joinPoint.getTarget().getClass());
        Object key = generateKey(cacheable, context);

        Object cacheObject = getCacheObject(cacheable, key);
        if (null != cacheObject) {
            return cacheObject;
        }

        Object result = joinPoint.proceed();
        if (null != result) {
            cacheObject(cacheable, key, result);
        }

        return result;
    }

    private Object getCacheObject(Cacheable cacheable, Object key) {
        Object cacheObject = cache.get(key);
        if (cacheable.serialize()) {
            cacheObject = SerializationUtils.deserialize((byte[]) cacheObject);
        }
        return cacheObject;
    }

    private void cacheObject(Cacheable cacheable, Object key, Object value) {
        if (cacheable.serialize()) {
            value = SerializationUtils.serialize(value);
        }
        cache.put(key, value, cacheable.timeout());
    }

}
public abstract class CacheAdviceSupport {
    private final ExpressionEvaluator evaluator    = new ExpressionEvaluator();
    private KeyGenerator              keyGenerator = new SimpleKeyGenerator();
    protected Cache                   cache;

    /**
     * Compute the key for the given caching operation.
     *
     * @return the generated key, or {@code null} if none can be generated
     */
    protected Object generateKey(Cacheable cacheable, CacheOperationContext context) {
        return context.generateKey(cacheable, ExpressionEvaluator.NO_RESULT);
    }

    protected CacheOperationContext getOperationContext(Method method, Object[] args, Object target, Class<?> targetClass) {
        return new CacheOperationContext(method, args, target, targetClass);
    }

    protected class CacheOperationContext {
        private final Method         method;
        private final Object[]       args;
        private final Object         target;
        private final Class<?>       targetClass;
        private final MethodCacheKey methodCacheKey;

        public CacheOperationContext(Method method, Object[] args, Object target, Class<?> targetClass) {
            this.method = method;
            this.args = extractArgs(method, args);
            this.target = target;
            this.targetClass = targetClass;
            this.methodCacheKey = new MethodCacheKey(method, targetClass);
        }

        public Object getTarget() {
            return this.target;
        }

        public Method getMethod() {
            return method;
        }

        public Object[] getArgs() {
            return this.args;
        }

        private Object[] extractArgs(Method method, Object[] args) {
            if (!method.isVarArgs()) {
                return args;
            }
            Object[] varArgs = ObjectUtils.toObjectArray(args[args.length - 1]);
            Object[] combinedArgs = new Object[args.length - 1 + varArgs.length];
            System.arraycopy(args, 0, combinedArgs, 0, args.length - 1);
            System.arraycopy(varArgs, 0, combinedArgs, args.length - 1, varArgs.length);
            return combinedArgs;
        }

        /**
         * Compute the key for the given caching operation.
         *
         * @return the generated key, or {@code null} if none can be generated
         */
        public Object generateKey(Cacheable cacheable, Object result) {
            if (StringUtils.hasText(cacheable.key())) {
                EvaluationContext evaluationContext = createEvaluationContext(result);
                return evaluator.key(cacheable.key(), this.methodCacheKey, evaluationContext);
            }
            return keyGenerator.generate(this.target, this.method, this.args);
        }

        private EvaluationContext createEvaluationContext(Object result) {
            return evaluator.createEvaluationContext(Arrays.asList(new Cache[] { cache }), this.method, this.args, this.target, this.targetClass, result);
        }

    }

    /**
     * @param keyGenerator the keyGenerator to set
     */
    public void setKeyGenerator(KeyGenerator keyGenerator) {
        this.keyGenerator = keyGenerator;
    }

    /**
     * @param cache the cache to set
     */
    public void setCache(Cache cache) {
        this.cache = cache;
    }

}

使用自定义注解进行缓存的类的配置:

<bean id="trackingListService" class="cn.vobile.service.trackinglist.TrackingListServiceImpl">
	<property name="trackingListDao" ref="trackingListDao"></property>
</bean>

TrackingListServiceImpl类里面进行缓存的方法:

@Cacheable(key = "'getTrackingListForCompany_'+#companyId+'_'+#orderNumber+'_'+#isContainSubList", timeout = 5, serialize = true)
public List<TrackingList> getTrackingListForCompany(String companyId, int orderNumber, boolean isContainSubList) {
	return trackingListDao.getTrackingListForCompany(companyId, orderNumber, isContainSubList );
}

注:这里面注解里的参数是根据每次调用的时候动态传入的,语法详见:Spring Expression Language (SpEL)

时间: 2024-10-06 03:49:40

Spring AOP+自定义注解实现缓存的相关文章

spring AOP + 自定义注解实现权限控制小例子

今天看了一下黑马程序员的视频,上面讲到一个使用spring AOP + 自定义注解的方式来实现权限控制的一个小例子,个人觉得还是可以借鉴,整理出来与大家分享. 需求:service层有一些方法,这些方法需要不同的权限才能访问. 实现方案:自定义一个PrivilegeInfo的注解,使用这个注解为service层中的方法进行权限配置,在aop中根据PrivilegeInfo注解的值,判断用户是否拥有访问目标方法的权限,有则访问目标方法,没有则给出提示. 关键技术:自定义注解及注解解析,spring

spring AOP自定义注解方式实现日志管理

转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在applicationContext-mvc.xml中要添加的 <mvc:annotation-driven />     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->     <conte

(转)利用Spring AOP自定义注解解决日志和签名校验

一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: boolean isValid = accountService.validSignature(appid, signature, client_signature); if (!isValid) return ErrorUtil.buildError(ErrorUtil.ERR_CODE_COM

利用Spring AOP自定义注解解决日志和签名校验

转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: boolean isValid = accountService.validSignature(appid, signature, client_signature); if (!

spring AOP自定义注解 实现日志管理

今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在applicationContext-mvc.xml中要添加的 <mvc:annotation-driven />     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->     <context:component-scan base-pac

使用Spring Aop自定义注解实现自动记录日志

百度加自己琢磨,以下亲测有效,所以写下来记录,也方便自己回顾浏览加深印象之类,有什么问题可以评论一起解决,不完整之处也请大佬指正,一起进步哈哈(1)首先配置文件: <!-- 声明自动为spring容器中配置@aspectj切面的bean创建代理 ,织入切面 --> <aop:aspectj-autoproxy /> <!-- 开启注解扫描 --> <context:component-scan base-package="com.ky.zhjd.**&q

Spring AOP 自定义注解获取http接口及WebService接口入参和出参

注解方法实现过程中可以采用如下获取方式:-以下为例  HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 1.定义两个方法注解,分别标记要处理的http接口及Webservice接口: http接口注解 1 2 3 4 5 @Retention(RetentionPolicy.RUNTIME) @Target({ El

Spring aop +自定义annotation

Spring aop +自定义注解 一.所需的jar 包: <!-- 导入java ee jar 包 --> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> </dependency> <!--spring ,springmvc--> <

使用Spring处理自定义注解

使用Spring处理自定义注解 本文只讲思想,不讲代码. 可能的两种方法 spring schema spring aop aspect 参考1 dubbo service 包名:com.alibaba.dubbo.config 参考2 spring mvc 包名:org.springframework.web.servlet.config 可以参考这两个的实现,利用schema添加自定义注解并处理自己的注解,注册搜索模块. 源码分析 通过schema添加配置解析如: 在 spring配置文件中