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