JAVA基础-注解

想必在项目中大家一定接触过不少注解,特别是在Spring项目中,那注解的作用是什么,有何意义?

什么是注解?

注解可以理解为一个标签,这个标签可以贴在类上,方法上,成员变量上。

注解用来标识某些特征,类似的可理解为Interface接口。

public @interface Table {

    String name() default "";
}

元注解

@Retention

Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

我们可以这样的方式来加深理解,@Retention 去给一张标签解释的时候,它指定了这张标签张贴的时间。@Retention 相当于给一张标签上面盖了一张时间戳,时间戳指明了标签张贴的时间周期。

@Retention(value = RetentionPolicy.RUNTIME)
public @interface Table {

    String name() default "";
}

 

上面的代码中,我们指定 Table注解可以在程序运行周期被获取到,因此它的生命周期非常的长。

@Documented

这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。

@Target

Target 是目标的意思,@Target 指定了注解运用的地方。

你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。@Target 有下面的取值

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
  • ElementType.CONSTRUCTOR 可以给构造方法进行注解
  • ElementType.FIELD 可以给属性进行注解
  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
  • ElementType.METHOD 可以给方法进行注解
  • ElementType.PACKAGE 可以给一个包进行注解
  • ElementType.PARAMETER 可以给一个方法内的参数进行注解
  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Inherited

Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Table {

    String name() default "";

}

@Table
class User{

}

class Member extends User{

}

 

@Repeatable

Repeatable 自然是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。

什么样的注解会多次应用呢?通常是注解的值可以同时取多个。比如一支笔,可写可读

@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Takes {
    Pen[] value() default {};
}


@Repeatable(value = Takes.class)
@interface Pen {
    String method() default "";
}


@Pen(method="write")
@Pen(method="read")
class XiaoMiPen{

}

如何使用注解

接下来我们自定义三个注解,用来模拟数据库操作

分别是@Table @Column @TableId

@Documented
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Table {

    String name() default "tableName";

}


@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface Column {
    String columnName() default "columnName";
}


@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface TableId {
    String Id() default "tableId";
}

创建一个User对象对应User表

package com.test.demo;

@Table(name = "user")
public class User {

    @TableId(Id = "user_id")
    private String userId;

    @Column(columnName = "user_name")
    private String userName;

    @Column(columnName = "age")
    private int age;

    @Column(columnName = "memo")
    private String memo;

    .....getset方法省略

}

利用Java反射我们可以这么做。此仅为demo,没有具体意义

        User user = new User("1","张三",18,"这是个逗比");

        StringBuilder sb = new StringBuilder();

        Class clazz = Class.forName(user.getClass().getName());
        //判断是不是对应有数据表
        Annotation annotation = clazz.getAnnotation(Table.class);
        if(Objects.isNull(annotation)){
            System.out.println("数据库没有这张表");
        }
        Table aClass = (Table) annotation;
        //获取表名
        String tableName = aClass.name();

        sb.append("select * from ").append(tableName);

        // TODO: 2020/6/29 excuteSql
        System.out.println(sb.toString());


        //获取主键
        String id = "";
        for (Field declaredField : clazz.getDeclaredFields()) {
            TableId column = declaredField.getAnnotation(TableId.class);
            if(!Objects.isNull(column) ){
                id = column.Id();
                System.out.println(id);
                declaredField.setAccessible(true);
                //查询
                sb.append(" where "+id +"=" + declaredField.get(user));
                System.out.println(sb);
            }
        }



        //获取其他字段
        for (Field declaredField : clazz.getDeclaredFields()) {
            Column column = declaredField.getAnnotation(Column.class);
            if(!Objects.isNull(column) ){
                String name = column.columnName();
                System.out.println(name);
            }
        }

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章