zoukankan      html  css  js  c++  java
  • 简单的注解剖析

      周边有许多同事只会使用注解,并不了解注解的原理。于是随手写一个小Demo,普及下注解的使用原理,顺便加深自己的理解。如有错误,欢迎大牛指正。

    1 注解类基本样式

    /**
     *
     * @author qpf
     * 此注解用于对表名的设置
     *
     */
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Table {
        String value();
    }
    

    2 注解类的元素解析

    元注解:
     
    总共有四个元注解,分别是:@Target,@Retention,@Documented,@Inherited,属于jdk注解,作用如下:
          @Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: 
              ElemenetType.CONSTRUCTOR----------------------------构造器声明 
              ElemenetType.FIELD --------------------------------------域声明(包括 enum 实例) 
              ElemenetType.LOCAL_VARIABLE------------------------- 局部变量声明 
              ElemenetType.METHOD ----------------------------------方法声明 
              ElemenetType.PACKAGE --------------------------------- 包声明 
              ElemenetType.PARAMETER ------------------------------参数声明 
              ElemenetType.TYPE--------------------------------------- 类,接口(包括注解类型)或enum声明 
               
         @Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括: 
              RetentionPolicy.SOURCE ---------------------------------注解将被编译器丢弃 
              RetentionPolicy.CLASS -----------------------------------注解在class文件中可用,但会被VM丢弃 
              RetentionPolicy.RUNTIME -------将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 
    @Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
     @Inherited 允许子类继承父类中的注解。
     
     
    注解使用方法:
    @Table("StudentInfo")
    public class StudentInfo extends BaseTable
    {
         //学生姓名
         @Column("name")
         private String name;
         
         //性别
         @Column("sex")
         private String sex;
    }
    
     
    注意:@Target设置了注解放在什么地方,设置为ElemenetType.FIELD,则需要将注解放置在属性的上方。设置为ElemenetType.TYPE,则需要放置在class上方。放错位置,编译器会报错。
    原理:把public @interface Table {String value();}和@Table("StudentInfo")
    放在一起看,其实注解就是返回你所设置的指定类型的值。其实就是在调用注解的value()方法,会返回String类型的值,值为注解中设置的“StudentInfo”。后面例子中会有详细介绍。还需注意一点,注解中返回的类型是有限定的,且方法一定要是无参的,不懂的可自行百度。
     

    3 利用注解实现小Demo

    3.1 需求内容

    1、有一张学生信息表,字段包括姓名,年级,班级,教师名,性别等;

    2、利用注解,对表实例的每个字段进行检查,并打印出查询sql   

    3.2 代码结构

    annotation:存放创建的注解。
    bean:存放数据库表所用到的javaBean
    test:main函数,用于测试并打印查询sql;
     

    3.3 注解类

    /**
     *
     * @author qpf
     * 此注解用于对表字段的设置
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Column {
        String value();
    }
    
    /**
     *
     * @author qpf
     * 此注解用于对表名的设置
     *
     */
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Table {
        String value();
    }
    

    3.4 学生信息表的javabean

    下面的代码删去了get和set方法。

    /**
     *
     * @author qpf
     * Table标签里为表名
     * Column标签里为数据库字段名
     */
    @Table("StudentInfo")
    public class StudentInfo extends BaseTable
    {
         //学生姓名
         @Column("name")
         private String name;
         
         //性别
         @Column("sex")
         private String sex;
         
         //年级
         @Column("grade")
         private String grade;
         
         //班级
         @Column("class_num")
         private String classNum;
         
         //班主任
         @Column("teacher")
         private String teacher;
         
         //总分
         @Column("total_scores")
         private String totalScores;
         
         //微信号
         @Column("weChat_num")
         private String weChatNum;
         
         //手机号
         @Column("tel_num")
         private String telNum;
         
         //父亲名
         @Column("father_name")
         private String fatherName;
         
         //母亲名
         @Column("mother_name")
         private String motherName;
    }
     
    

      

    3.5 AnnotationTest方法

    public class AnnotationTest {
         /**
          * 需求设计:
          *    1、有一张学生信息表,字段包括姓名,年级,班级,教师名,性别等;
          *    2、利用注解,对每个字段的组合条件进行检查,并打印出sql     
          */
         public static void main(String[] args)
         {
             // TODO Auto-generated method stub
             StudentInfo studentInfo=new StudentInfo();
             studentInfo.setName("Tom");
             studentInfo.setSex("men");
             studentInfo.setTelNum("18255005147,18255005148,18255005149");
             studentInfo.setWeChatNum("qpf123456");
             String sql=querySql(studentInfo);
             System.out.println((sql==null)?"":sql);
         }
         public static String querySql(BaseTable table)
         {
             //获取类加载器
             Class<?> cTable=table.getClass();
             //判断类中是否包含Table的注解
             boolean tableIsExists=cTable.isAnnotationPresent(Table.class);
             
             //判断是否为表实例
             if(!tableIsExists)
             {
                  return null;
             }
             
             //获取表名
             String tableName=cTable.getAnnotation(Table.class).value();
             
             //初始化表查询语句
             StringBuilder builder=new StringBuilder("select * from");
             builder.append(" "+tableName+" where 1=1");
             
             //获取表实例中的所有字段
             Field[] fields=cTable.getDeclaredFields();
             
             
             try
             {
                  for (Field field : fields)
                  {
                       //判断是否为表数据字段
                    boolean columnIsExist=field.isAnnotationPresent(Column.class);
                       
                       if(!columnIsExist)
                       {
                           continue;
                       }
                       
                       //判断表数据字段的值是否为null
                       field.setAccessible(true);
                       String fieldValue=(String)field.get(table);
                       if(null==fieldValue || "".equals(fieldValue))
                       {
                           continue;
                       }
                       
                       //检测到需要拼接字段时,再获取数据库字段名
                       String columnName=field.getAnnotation(Column.class).value();
                       
                       //需要用in的字段处理
                       if(fieldValue.contains(","))
                       {
                           builder.append(" and "+columnName+" in(");
                           String[] strs=fieldValue.split(",");
                           
                           for (int i = 0; i < strs.length; i++)
                           {
                                builder.append("'"+strs[i]+"'");
                                if(i!=strs.length-1)
                                {
                                     builder.append(",");
                                }
                           }
                                
                           builder.append(")");
                       }
                       else
                       {
                        builder.append(" and "+columnName+"="+"'"+fieldValue+"'");
                       }
                       
                  }
             }
             catch (Exception e)
             {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
             }
             
             return builder.toString();
         }
    }
    

      

    上面方法打印出的查询sql语句为:

    select * from StudentInfo where 1=1 and name='Tom' and sex='men' and weChat_num='qpf123456' and tel_num in('18255005147','18255005148','18255005149')
    

      

     
  • 相关阅读:
    【Jmeter】 jmeter-server.bat 无法启动
    Jmeter场景设置与监听
    Jmeter性能测试配置
    【VMware】“该虚拟机似乎正在使用中”
    Jmeter介绍以及脚本制作与调试
    性能测试简介
    robotframework配置邮箱服务器
    Java冒泡排序
    LN(A)MT单机版架构部署
    Openstack之八:部署自服务网络
  • 原文地址:https://www.cnblogs.com/qpf1/p/9161690.html
Copyright © 2011-2022 走看看