Java注解解析

2018-01-16  本文已影响0人  Mr丶sorrow

概念

注解是Java提供的一种 源程序中的元素关联任何信息和任何元数据的途径和方法。

Java常见注解

注解分类

自定义注解

image.png

4. 如果注解只有一个成员,则成员名必须取名value(),在使用时可以忽略成员名和赋值

号(=);

5. 成员类型是受限的,合法的类型包括原始数据类型和String,Class,Annotation,Enumeration

6. 注解类可以没有成员,没有成员的注解称为标识注解

image.png

使用自定义注解


/* 自定义的注解类 */

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Description{

  int age() default 10;

  String author();

  String desc();

}

--------------------------------------------------------------------------------

/*

使用注解的语法:

@<注解名>(<成员名1>=<成员值1>,<成员名1>=<成员值1>,...)

*/

@Description(desc="I am eyeColor",author="Mooc boy",age=18)

public String eyeColor(){

  return "red";

}

解析注解

概念:通过反射获取类、函数或成员的运行时注解信息,从而实现动态控制程序运行的逻辑。

步骤

示例


//自定义注解 Description.java

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Description{

  int age() default 10;

  String author();

  String desc();

}


// Person.class 用自定义注解修饰

@Description(desc="human class", author="wgp", age=20)

public class Person {

  @Description(desc="walk method", author="gp", age=21)

  public void walk(){

    System.out.println("human can walk!");

  }

}


// 注解解析类 Test.class

import java.lang.annotation.Annotation;

import java.lang.reflect.Method;

public class Test {

public static void main(String[] args) {

  try {

    //1\. 使用类加载器加载类

    Class c = Class.forName("Person");

    //2\. 找到类上面的注解

    boolean isExist=c.isAnnotationPresent(Description.class);//isAnnotationParse()判断类上是否存在Description这样的注解

    if(isExist){

      //3.获得注解实例

      Description d = (Description)c.getAnnotation(Description.class);

      System.out.println(d.desc());

    }

    //4.找到方法上的注解

    Method[] mts = c.getMethods();

    for (Method mt : mts) {

      if(mt.isAnnotationPresent(Description.class)){

        Description d2 = (Description)mt.getAnnotation(Description.class);

        System.out.println(d2.author());

      }

    }

    //另外一种获取类上的注解的途径

    Annotation[] annos = c.getAnnotations();

    for (Annotation anno : annos) {

      if(anno instanceof Description){

        System.out.println(((Description) anno).author());

      }

    }

    //另一种获取方法上的注解的途径

    for (Method mt : mts){

      Annotation[] annos2 = mt.getAnnotations();

      for (Annotation anno : annos2) {

        if(anno instanceof Description){

          System.out.println(((Description) anno).desc());

        }

      }

    }

  } catch (Exception e) {

    //TODO: handle exception

  }

}

}

项目案例

说明

代替Hibernate的解决方案,用在项目的持久层,核心代码就是用自定义注解实现的。

需求

1. 有一张用户表,字段包含id,用户名,密码,地址,手机号;

2. 方便的对每个字段或者每个字段的组合进行检索,并打印出SQL。

分析

1. 首先肯定有一个关于用户的JavaBean,包含所有用户信息;

2. 有了JavaBean需要将属性与字段匹配,也就是ORM;

3. 匹配完相当于拼接SQL语句时,知道表名和字段名称了,还缺少where中的字段值是多少;

4. 通过用户类的getter方法来获取字段值为多少,拼接完整SQL语句。

代码实现

1. 用户类,我们希望用@Table和@Cloumn来绑定;


/**

* User:用户JavaBean

*/

@Table("user")

public class User {

  @Column("id")

  public Integer id;

  @Column("user_name")

  public String userName;

  @Column("password")

  public String passWord;

  @Column("address")

  public String address;

  @Column("phone_num")

  public String phoneNum;

  public void setId(Integer id) {

    this.id = id;

  }

  public void setUserName(String userName) {

    this.userName = userName;

  }

  public void setPassWord(String passWord) {

    this.passWord = passWord;

  }

  public void setAddress(String address) {

    this.address = address;

  }

  public void setPhoneNum(String phoneNum) {

    this.phoneNum = phoneNum;

  }

  public Integer getId() {

    return id;

  }

  public String getUserName() {

    return userName;

  }

  public String getPassWord() {

    return passWord;

  }

  public String getAddress() {

    return address;

  }

  public String getPhoneNum() {

    return phoneNum;
  
  }

}

2. 自定义@Table注解和@Column注解;


import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Table{

  String value();

}

--------------------------------------------------------------------------

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface Column{

  String value();

}

3. 根据反射来拼接出全部的SQL语句。


import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class UserDao {

  public static void main(String[] args) {

    User user1 = new User();

    user1.setId(0);

    User user2 = new User();

    user2.setUserName("ping");

    User user3 = new User();

    user3.setAddress("beijing");

    user3.setPhoneNum("10101010101");

    String sql1 = query(user1); //查询id为0用户

    String sql2 = query(user2); //查询用户名含有ping的用户

    String sql3 = query(user3); //查询满足多个条件的用户

    System.out.println(sql1);

    System.out.println(sql2);

    System.out.println(sql3);
  }

  public static String query(User user) {

    StringBuilder sBuilder = new StringBuilder();

    Class clazz = user.getClass();

    // 获取表名

    if(!clazz.isAnnotationPresent(Table.class)){

      return null;

    }

    Table table = (Table) clazz.getAnnotation(Table.class);

    String tableName = table.value();

    sBuilder.append("select * from ").append(tableName).append(" where 1 = 1");

    // 获取所有字段名+值

    Field[] fields = clazz.getDeclaredFields();

    for (Field field : fields) {

      if(!field.isAnnotationPresent(Column.class)){

        continue;

      }

      Column column = field.getAnnotation(Column.class);

      String columnName = column.value(); //字段名

      String fieldName = field.getName(); //属性名

      String getMethodName = "get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1); //get方法名

      Object fieldValue = null; //属性值(先提升为Object类型)

      try {

        Method getMethod = clazz.getMethod(getMethodName);

        fieldValue = getMethod.invoke(user); //执行get方法获取值

      } catch (Exception e) {

        e.printStackTrace();

      }

      //继续拼接SQL

      if(fieldValue == null){

        continue;

      }

      sBuilder.append(" and ").append(columnName);

      if(fieldValue instanceof String){

        sBuilder.append("='").append(fieldValue).append("'");

      } else if(fieldValue instanceof Integer){

        sBuilder.append("=").append(fieldValue);

      }

    }

    return sBuilder.toString();
  }

}

参考资料

上一篇下一篇

猜你喜欢

热点阅读