001-注解Annotaion-最简单的注解


             Java中叫注解                       C#中叫特性


举个常见的例子,ORM中,对象与数据表进行映射,通常设置主键后,要做主键入库前的校验。

  • 写个实体类
package entity;

import annotaion.runtime.PrimaryKey;

public class Book {

    @PrimaryKey // 通过注解标明它是一个主键字段
    private Integer id;

    private String name;

    public Book() {
    }

    public Book(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

给id增加注解,相当于打了个标签,不管这个字段是叫什么,它都代表是个主键字段。

  • 注解声明
package annotaion.runtime;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/*
* 主键注解
* */
@Retention(RetentionPolicy.RUNTIME) // 有效范围,RUNTIME:当运行时,仍可以获取到
@Target(ElementType.FIELD) // 注解可以用在什么元素上,Field:表示字段
public @interface PrimaryKey {
}

注解-说白了就是个标签,给谁贴上谁就有了这个特性。

  • 注解使用

当然,给某个对象或者字段贴上标之后,需要有地方去识别,这是最关键的。

package tzlorm;

import annotaion.runtime.PrimaryKey;

import java.lang.reflect.Field;

public class Checker {
    public static boolean checkData(Object data) throws Exception {
        // 取出对象所有字段
        Field[] declaredFields = book.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 从字段中,尝试取主键的标注
            PrimaryKey annotation = declaredField.getAnnotation(PrimaryKey.class);
            if(annotation == null) continue; // 没有标注,说明不需要检测

            // 读取私有字段的值
            // 1,开启权限,直接读取,开启权限破坏了封装特性,但可以增加访问速度,提高性能
            declaredField.setAccessible(true);
            Object value = declaredField.get(book);

            // 2,通过封装的getter读取
//            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(declaredField.getName(), book.getClass());
//            Object value = propertyDescriptor.getReadMethod().invoke(book);

            if(value == null) return false;
        }
        return true;
    }
}

综合测试

import entity.Book;
import tzlorm.Checker;

public class AppRun {
    public static void main(String[] args) {
        try {
            // 创建一个实例
            Book book = new Book();
            book.setId(3);

            // 需要做主键的非空判断,封装一个统一的检测器来做这件事
            boolean isPass = Checker.checkData(book);
            if(!isPass) throw new Exception("主键不能为空");

            // 将数据入库
            save2db(book);
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    public static int save2db(Book book){
        System.out.println("数据已入库");
        return 1;
    }
}