Java 究竟是如何通过反射操作注解的?

上一讲,我介绍了 Java 是如通过反射动态创建与使用对象。本讲将介绍 Java 是如何通过反射操作注解的?

1、通过反射获取运行时类的完整结构

我们可以通过反射获取运行时类的完整结构,主要包括:字段(Field)、方法(Method)、构造器(Constructor)、父类(Superclass)、接口(Interface)、注解(Annotation)等。

如:

import java.lang.annotation.ElementType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 获取运行时类的完整结构
 */

public class test {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("java.lang.String");//反射获取String类的Class对象

        System.out.println("全类名:" + c1.getName());//获取全类名
        System.out.println("类的简单名称:" + c1.getSimpleName());//获取类的简单名称

        System.out.println("---------------------------");
        //获取类的public属性
        Field[] fields = c1.getFields();
        for (Field field : fields ) {
            System.out.println("类的public属性:" + field);
        }

        System.out.println("---------------------------");
        //获取类的全部属性
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field field : declaredFields ) {
            System.out.println("类的全部属性:" + field);
        }

        System.out.println("---------------------------");
        //获取本类及父类的public方法
        Method[] methods = c1.getMethods();
        for (Method method : methods ) {
            System.out.println("本类及父类的public方法:" + method);
        }

        System.out.println("---------------------------");
        //获取本类的全部方法
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method method : declaredMethods ) {
            System.out.println("本类的全部方法:" + method);
        }

        System.out.println("---------------------------");
        //获取类的public构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors ) {
            System.out.println("类的public构造器:" + constructor);
        }

        System.out.println("---------------------------");
        //获取类的所有构造器
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors ) {
            System.out.println("类的所有构造器:" + declaredConstructor);
        }
    }
}

运行结果如下图所示(部分):

Java 究竟是如何通过反射操作注解的?

2、通过反射操作注解

下面我们将通过练习ORM,学习如何通过反射操作注解。

2.1、什么是ORM

ORM,即:Object-Relational Mapping(对象关系映射)。它的作用是在关系型数据库和业务实体对象之间作一个映射。

Java 究竟是如何通过反射操作注解的?


其中:

  • 类和表结构对应;

  • 属性和字段对应;

  • 对象和记录对应。

常用的 Java ORM 框架有 Hibernate 和 Mybatis

2.2、利用注解与反射完成类和表结构的映射关系

例:利用注解与反射完成Student类和db_student表结构(字段分别为:db_id、db_age、db_name)的映射关系。

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射操作注解
 */

public class test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("Student");//通过反射获取Student类的Class对象

        //通过反射获取Student类的注解信息
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        System.out.println("-----------------------");
        //通过反射获取Student类的注解的value值
        TableName tableName = (TableName) c1.getAnnotation(TableName.class);
        String value = tableName.value();
        System.out.println(value);

        System.out.println("-----------------------");
        //通过反射获取Student类中name属性的注解信息
        Field name = c1.getDeclaredField("name");
        Annotation[] annotations1 = name.getAnnotations();
        for (Annotation annotation : annotations1) {
            System.out.println(annotation);
        }

        System.out.println("-----------------------");
        //通过反射获取Student类中name属性的注解的值
        FieldName annotation = name.getAnnotation(FieldName.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
}

//实体类
@TableName("db_student")//使用自定义类名的注解,将类名和数据库表名对应
class Student{
    @FieldName(columnName = "db_id",type = "int",length = 10)//使用自定义属性的注解,将类的id属性和数据库的db_id字段对应
    private int id;
    @FieldName(columnName = "db_age",type = "int",length = 10)//使用自定义属性的注解,将类的age属性和数据库的db_age字段对应
    private int age;
    @FieldName(columnName = "db_name",type = "varchar",length = 3)//使用自定义属性的注解,将类的name属性和数据库的db_name字段对应
    private  String name;

    //无参构造器
    public Student() {
    }

    //有参构造器
    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + ''' +
                '}';
    }
}

//自定义类名的注解(用于类和表结构对应)
@Target(ElementType.TYPE)//适用于类
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@interface TableName{
    String value();//表名
}

//自定义属性的注解(用于属性和字段对应)
@Target(ElementType.FIELD)//适用于属性
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@interface FieldName{
    String columnName();//列名
    String type();//数据类型
    int length();//长度
}

关注 “阿汤笔迹” 微信公众号,获取更多学习笔记。

原文始发于微信公众号(阿汤笔迹):Java 究竟是如何通过反射操作注解的?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/236751.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!