spring aop aspect + annotation实现缓存命中判断
2016-06-02 14:22
603 查看
最近看到了一种使用aop和注解的方式实现缓存命中判断的实现方式,觉得非常不错。借鉴过来,进行分享。
1、引入spring和aspect相关依赖
2、创建Cache注解类,用于标识需要添加缓存的方法。
3、创建CacheType类,标识缓存的类型,目前仅有Object和List两种,其他的可以根据项目的需求自己添加。
4、创建Cache切面类,用于解析Cache注解,实现缓存命中判断。
5、缓存添加、获取实现类,该例子仅使用内存作为缓存,在实际的项目中,可能会使用redis、memcache等缓存。
6、spring配置文件:
7、实际使用:CacheService
注意:
JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:
ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法:
1、引入spring和aspect相关依赖
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.6</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency>
2、创建Cache注解类,用于标识需要添加缓存的方法。
@Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Cache { //缓存时间,默认60秒 int expire() default 60; //缓存实体类型 Class<?> clazz(); //缓存中存放的具体类型 CacheType cacheType(); }
3、创建CacheType类,标识缓存的类型,目前仅有Object和List两种,其他的可以根据项目的需求自己添加。
public enum CacheType { OBJECT, LIST, ; }
4、创建Cache切面类,用于解析Cache注解,实现缓存命中判断。
public class CacheAspect { private Logger logger = LoggerFactory.getLogger(CacheAspect.class); public Object doAround(ProceedingJoinPoint pjp) throws Throwable { MethodSignature ms = (MethodSignature)pjp.getSignature(); Method method = ms.getMethod(); Cache annotation = method.getAnnotation(Cache.class); //获取注解信息 int expire = annotation.expire(); Class<?> clazz = annotation.clazz(); CacheType cacheType = annotation.cacheType(); //获取类名、方法名、参数名 String className = pjp.getTarget().getClass().getSimpleName(); String methodName = pjp.getSignature().getName(); Object[] args = pjp.getArgs(); StringBuffer sb = new StringBuffer(); for(Object arg : args) { if(arg != null) { sb.append("_").append(arg.toString()); } } //用类名、方法名、参数名作为缓存的key String cacheKey = className.concat("_").concat(methodName).concat(sb.toString()); Object obj = CacheUtils.getFromCache(cacheKey, clazz, cacheType); //命中缓存,直接返回信息 if(obj != null) { logger.info("cache hit for key:"+cacheKey); return CallResult.success(obj); } else { //未命中缓存,查询结果,并放到缓存中 CallResult result = (CallResult)pjp.proceed(); if(result.isSuccess()) { logger.info("put to cache for key:"+cacheKey); CacheUtils.put2Cache(cacheKey, result.getResultObject(), expire); } return result; } } }
5、缓存添加、获取实现类,该例子仅使用内存作为缓存,在实际的项目中,可能会使用redis、memcache等缓存。
public class CacheUtils { private static Logger logger = LoggerFactory.getLogger(CacheUtils.class); private static ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); public static void put2Cache(String key, Object result, int expire) { String str = JSON.toJSONString(result); map.put(key, str); } public static Object getFromCache(String key, Class clazz, CacheType cacheType) { try { String result = map.get(key); if(StringUtils.isNotBlank(result)) { if(CacheType.LIST.equals(cacheType)) { List list = JSON.parseObject(result, List.class); List retList = new ArrayList(); for(Object obj : list) { retList.add(JSON.parseObject(obj.toString(), clazz)); } return retList; } else { return JSON.parseObject(result, clazz); } } } catch (Exception e) { logger.error("getFromCache exception",e); } return null; } }
6、spring配置文件:
<aop:aspectj-autoproxy proxy-target-class="true" /> <bean id="cacheService" class="com.demo.lizhy.service.impl.CacheServiceImpl" /> <bean id="cacheAspect" class="com.demo.lizhy.service.aspect.CacheAspect" /> <aop:config> <aop:aspect ref="cacheAspect"> <aop:around method="<strong>doAround</strong>" pointcut="@annotation(com.demo.lizhy.service.aspect.Cache)" /> </aop:aspect> </aop:config>
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
7、实际使用:CacheService
public class CacheServiceImpl implements CacheService { private Logger logger = LoggerFactory.getLogger(CacheServiceImpl.class); @Override @Cache(expire = 100, clazz = String.class, cacheType = CacheType.OBJECT) public CallResult<String> getCacheInfo(String name) { logger.info("search from db========="); return CallResult.success(name); } }
注意:
JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:
ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法:
相关文章推荐
- java-注解annotation
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- yui3的AOP(面向切面编程)和OOP(面向对象编程)
- JavaScript AOP编程实例
- 使用AOP改善javascript代码
- 初识SmartJS - AOP三剑客
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解