自定义注解

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 自定义注解

自定义注解

  1. 自定义注解
/**
 1. 该注解主要实现查询操作. 
 2. 有缓存查询缓存,没缓存查询数据库
 3. @author Administrator
 4. 
 5. 操作规范:(具体实现在CacheAspect类中)
 6.     key: 
 7.        1.用户没有赋值
 8.           如果key为"",表示用户使用自动生成的key
 9.           key生成策略为:包名.类名.方法名.拼接第一个参数
 10.        2.如果用户赋值
 11.           key:使用用户的数据
 12.  seconds:
 13.     如果时间不为0,表示用户需要设定超时时间
 */
@Target({ElementType.METHOD}) //对方法生效
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache_Find {
   String key() default "";
   int  seconds() default 0;
}
  1. 对自定义注解的逻辑定义切面
//切面 = 切入点 + 通知
@Aspect          //标识切面
@Component    //交给spring容器管理
public class CacheAspect {
   @Autowired(required = false)
   private JedisCluster jedis; //注入redis集群对象
   /**
    * 利用AOP规则:动态获取注解对象
    * 步骤:
    *     1.根据key查询redis.
    *  2.没有数据,需要让目标方法执行.查询的结果保存redis
    *  3.将json串转化为返回值对象 返回.
    * @param joinPoint
    * @param cacheFind
    * @return
    */
   @Around("@annotation(cacheFind)")
   public Object around(ProceedingJoinPoint joinPoint, Cache_Find cacheFind) {
      //cacheFind必须和@Around("@annotation(cacheFind)")中的cacheFind保持一致
      Object data = null;
      String key = getKey(joinPoint,cacheFind);
      //1.从redis中获取数据
      String result = jedis.get(key);
      //2.判断缓存中是否有数据
      try {
         if(StringUtils.isEmpty(result)) {
            //2.1缓存中没有数据
            data = joinPoint.proceed();//目标方法执行,即添加了@Cache_Find注解的方法执行,查询数据库
            //2.2将返回值结果,转化为jsonStr
            String json = ObjectMapperUtil.toJSON(data);
            //2.3判断用户是否编辑时间
            //如果有时间,必须设定超时时间.
            if(cacheFind.seconds()>0) {
               int seconds = cacheFind.seconds();
               jedis.setex(key,seconds, json);//有超时时间的方法
            }else {
               jedis.set(key,json);//没有超时时间的方法
            }
            System.out.println("AOP查询数据库!!!!!");
         }else {
            //表示缓存数据不为空,将缓存数据转化为对象
            Class returnClass = getReturnClass(joinPoint);
            data = ObjectMapperUtil.toObject(result,returnClass);
            System.out.println("AOP查询缓存!!!!");
         }
      } catch (Throwable e) {
         e.printStackTrace();
         throw new RuntimeException(e);//全局处理了RuntimeException
      }
      return data;
   }
   /**
    * 获取目标方法的返回值类型,即添加了@Cache_Find注解的方法的返回值类型
    * @param joinPoint
    * @return
    */
   private Class getReturnClass(ProceedingJoinPoint joinPoint) {
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      return signature.getReturnType();
   }
   /**
    * 动态获取key
    * @param joinPoint
    * @param cacheFind
    * @return
    */
   private String getKey(ProceedingJoinPoint joinPoint, Cache_Find cacheFind) {
      String key = cacheFind.key(); //如果使用@Cache_Find注解时,给了key值,使用给的key值
      if(StringUtils.isEmpty(key)) { //如果使用@Cache_Find注解时,没有给key值,则自动生成一个key值
         //获取添加了@Cache_Find注解的方法所在的全类名
         String className = joinPoint.getSignature().getDeclaringTypeName();
         //获取添加了@Cache_Find注解的方法名
         String methodName = joinPoint.getSignature().getName();
         if(joinPoint.getArgs().length>0)
            //joinPoint.getArgs()[0] 是获取添加了@Cache_Find注解的方法的第一个参数
            key = className+"."+methodName+"::" + joinPoint.getArgs()[0];
         else 
            key = className+"."+methodName;
      }
      return key;
   }
}
  1. 切面中使用到的一个工具类ObjectMapperUtil
/**
 * 作用: 实现对象与JSON串之间的转化
 * @author Administrator
 *
 */
public class ObjectMapperUtil {
   
   //常量对象 可以调用对象的方法 线程安全 不安全???
   private static final ObjectMapper MAPPER = new ObjectMapper();
   
   /**
    * 将检查异常转化为运行时异常.
    * @param data
    * @return
    */
   public static String toJSON(Object data) {
      String json = null;
      try {
         json = MAPPER.writeValueAsString(data);
      } catch (JsonProcessingException e) {
         e.printStackTrace();
         throw new RuntimeException(e);
      }
      
      return json;
   }
   
   
   /**
    * 根据JSON转化为对象 
    * 参数:json数据,Class
    * 返回值:由用户决定.
    */
   @SuppressWarnings("unchecked")
   public static <T> T toObject(String json,Class<T> target) {
      T obj = null;
      try {
         obj = MAPPER.readValue(json, target);
      } catch (IOException e) {
         e.printStackTrace();
         throw new RuntimeException(e);
      }
      return obj;
   }
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
Java 编译器 数据安全/隐私保护
自定义注解与AOP结合使用
自定义注解与AOP结合使用
106 0
|
Java
简单、快速教你自定义注解
简单、快速教你自定义注解
65 0
|
1月前
|
存储 缓存 Java
自定义注解
自定义注解
29 0
自定义注解
|
3月前
|
Java 编译器 程序员
Java注解,元注解,自定义注解的使用
本文讲解了Java中注解的概念和作用,包括基本注解的用法(@Override, @Deprecated, @SuppressWarnings, @SafeVarargs, @FunctionalInterface),Java提供的元注解(@Retention, @Target, @Documented, @Inherited),以及如何自定义注解并通过反射获取注解信息。
Java注解,元注解,自定义注解的使用
|
6月前
|
Java Spring
自定义注解+AOP
自定义注解+AOP
57 1
|
XML Java 编译器
【学习总结】注解和元注解
【学习总结】注解和元注解
【学习总结】注解和元注解
|
XML 存储 Java
java注解-自定义注解的实现
java注解-自定义注解的实现
122 0