快速理解JAVA注解(Annotation)

JAVA注解的本质

  1. 注解本质上是一类模板。
  2. 注解的读取基于JAVA语言的反射。通过反射可以拿到一个类的包含的所有东西(方法、属性、注解)。
  3. 注解的功能实现还是以代码进行实现。注解的初始化由JAVA底层读取实现。
  4. 注解不一定有实际的用处。例如:@SuppressWarnings仅仅用来指示编译器去忽略注解中声明的警告。

以下为两个常见的例子:

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。防止低级错误。
  • @Column - 用来映射实体类字段与数据库字段并有添加字段约束的功能。可以防止数据库字段带有下划线导致的问题。

元注解

  • 元注解是用来定义注解的基本使用规范。

  • 通过元注解可以进行自定义注解。例如:@Column注解的实现方式,通过反射读取实体类属性与对应注解中的参数name,再通过name拼接成SQL进行数据库查询。(实体类字段–@Column注解name值–数据库字段)

  • 元注解有 @Retention、@Documented、@Target、@Inherited这四种是最基本注解;jdk1.8新增了@Repeatable注解

@Retention

作用是被修饰的注解可以保存多久,这个注解需要使用参数。这个参数的类型是RetentionPolicy,所以使用这个注解就要对value赋值。
value的值有且仅有三个:

  • RetenionPolicy.CLASS 编译器把该注解记录在class文件中。当运行java程序时,JVM不可获取注解信息。这是默认值!
  • RetenionPolicy.RUNTIME编译器把该注解记录在class文件中。当运行java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息。
  • RetenionPolicy.SOURCE 该注解只保存在源代码中,编译器直接丢弃该注解。

@Documented

指定被修饰的注解类将被javadoc工具提取成文档,如果定义注解类时使用了这个注解修饰,则所有使用该注解修饰的程序员苏API文档将会包含该注解说明。
例如:@Documentedpublic @interface Testable{}

@Target

@Target也只能修饰一个注解定义,作用是指定被修饰的注解能用于修饰哪些程序单元,@Target也包含了一个value值,他的值只能是下面的:ElementType.

取值使用范围
METHOD可用于方法上
TYPE可用于类或者接口上
ANNOTATION_TYPE可用于注解类型上(被@interface修饰的类型)
CONSTRUCTOR可用于构造方法上
FIELD可用于域上
LOCAL_VARIABLE可用于局部变量上
PACKAGE用于记录java文件的package信息
PARAMETER可用于参数上

@Inherited

这个注解指定被他修饰的注解将具有继承性;如果某个类使用了@Xxx,则其子类将自动被@Xxx修饰

@Repeatable

jdk1.8才有的此注解,标识某注解可以在同一个声明上使用多次。例如:对于一个字段已经有@Column注解后,无法在此字段上再次添加@Column注解,如在注解@Column的定义中加上@Repeatable注解则可以同时添加多个。

注解的使用

以@Column为例

  • 注解的定义
// 作用于方法上或属性上
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String name() default "";
    boolean unique() default false;
    boolean nullable() default true;
    boolean insertable() default true;
    boolean updatable() default true;
    String columnDefinition() default "";
    String table() default "";
    int length() default 255;
    int precision() default 0;
    int scale() default 0;
}
  • 注解的使用
// 属性上添加注解,并将name赋值为数据库字段列名
@Column(name = "user_name")
private String userName;
  • 注解的实现
    以下为代码片段,"…"代表省略。有兴趣可以查看底层源码包(tk.mybatis:mapper:3.4.0)
// tkMybaits底层实现@Column注解
// 1、反射获取实体字段注解,设置查询数据库对应的字段;循环调用此方法遍历实体类所有字段。
private static void processField(EntityTable entityTable, Style style, EntityField field) {
	// 排除字段
    if (field.isAnnotationPresent(Transient.class)) {
        return;
    }
	......
	EntityColumn entityColumn = new EntityColumn(entityTable);
	......
	String columnName = null;
	// 判断字段是否有该注解
	if (field.isAnnotationPresent(Column.class)) {
	    Column column = field.getAnnotation(Column.class);
	    columnName = column.name();
	    ......
	}
	......
	// 将注解中name赋值EntityColumn对象中Column字段
	entityColumn.setColumn(columnName);
	......
}

// 2、拼接数据库查询SQL字段
public static String getAllColumns(Class<?> entityClass) {
    Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
    StringBuilder sql = new StringBuilder();
    // 取EntityColumn对象中Column字段拼接要查询数据库的字段
    for (EntityColumn entityColumn : columnList) {
        sql.append(entityColumn.getColumn()).append(",");
    }
    return sql.substring(0, sql.length() - 1);
}
  • 自定义注解
    自定义注解本质上就是JAVA语言的一种扩展。了解了以上注解的本质,就可以写出自己的注解。以上代码还包含了对@Transient注解的处理,不妨找一下,加深理解。

参考文章:
https://baike.baidu.com/item/%E6%B3%A8%E8%A7%A3/22344968#viewPageContent
https://blog.csdn.net/qq1404510094/article/details/80577555
https://www.runoob.com/w3cnote/java-annotation.html.
https://blog.csdn.net/xsp_happyboy/article/details/80987484

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值