对于java的注解, 自己已经使用了相当长的时间, spring中对注解的使用无处不在,但对它的了解并不深入, 本周对注解进行了较为深入的学习。
Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。
上面的是java注解的官方解释,相信看了以后本来明白的仍然明白,但是不明白的却还是不明白。
我感觉注解可以简单理解为是一个标签
, 若是在类或属性等上面有什么标签
,我们就需要对其进行某些处理,如何处理呢?别急,后面会说。
public @interface TestAnnotion { }
一个最简单的注解定义方式就像上面一样, 和接口很像对不对,只是多了一个@
符号,注解实际上是一种继承自接口java.lang.annotation.Annotation
的特殊接口,jdk文档有如下说法
An annotation type declaration specifies a new annotation type, a special kind of interface type. To distinguish an annotation type declaration from a normal interface declaration, the keyword interface is preceded by an at-sign (@)
……
The direct superinterface of every annotation type is java.lang.annotation.Annotation.
注释类型声明指定一种新的注释类型,一种特殊的接口类型。要将注释类型声明与普通接口声明区分开来,关键字接口前面有at符号(@)
……
每个注释类型的直接上接口是java.lang.annotation.annotation。
所以上面定义的TestAnnotion
,可以理解成这样
public interface TestAnnotion extends Annotation { }
这篇文章和这篇文章
通过反编译给我们了更直观的展示这个结论。
想要自定义注解就肯定要了解元注解
我们知道 spring data jpa
中 如果给某个类加上@Entity
的注解,spring就会为我们创建相应的数据表,
接下来我们就实现一个注解:他会生成创建一个数据表的sql,然后打印出来(执行也是的原理,咱就不执行了), 要实现这个功能,需要和反射相结合,若是还未学习过反射可以先通过这篇文章学习一下。
Entity.java
@Target(ElementType.TYPE) // 作用于类 @Retention(RetentionPolicy.RUNTIME) public @interface Entity { }
Member.java
@Entity public class Member { String name; Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
TableCreator.java
public class TableCreator { public static void main(String[] args) throws Exception { // 获取Member的实例变量 Class<?> cl = Member.class; // 查找该类上是否有相应的注解 Entity entity = cl.getAnnotation(Entity.class); if (entity == null) { System.out.println( "该类没有Entity注解"); return; } // 获取数据库的名 String tableName = cl.getName().toLowerCase(); // 定义像对象的属性 List<String> columnDefs = new ArrayList<>(); for (Field field : cl.getDeclaredFields()) { String columnName = field.getName().toLowerCase(); String columnDef = columnName + " varchar(50)"; columnDefs.add(columnDef); } // 构造sql语句 StringBuilder createCommand = new StringBuilder( "create table " + tableName + "("); for (String columnDef : columnDefs) createCommand.append("\n ").append(columnDef).append(","); String tableCreate = createCommand.substring( 0, createCommand.length() - 1) + ");"; System.out.println("生成的sql语句为:\n" + tableCreate); } }
像上面这种处理提取和处理 Annotation 的代码统称为 APT(Annotation Processing Tool)。
#### 注解成员变量
我们可以在注解中设置成员变量,形如
@Target(ElementType.TYPE) // 作用于类 @Retention(RetentionPolicy.RUNTIME) public @interface Entity { // name 值必须赋值, 若不设置默认值则必须在使用处赋值 String name() default ""; }
赋值方式
同时,还有一点需要注意的是,如果你在注解中定义了名为 value
的元素,并且在使用该注解时,value
为唯一一个需要赋值的元素,你就不需要使用键—值对的语法,你只需要在括号中给出 value
元素的值即可。这可以应用于任何合法类型的元素。这也限制了你必须将元素命名为 value
,不过在上面的例子中,这样的注解语句也更易于理解:
@Target(ElementType.TYPE) // 作用于类 @Retention(RetentionPolicy.RUNTIME) public @interface Entity { //value 为唯一一个需要赋值的元素,你就不需要使用名—值对的语法 String value(); String test() default ""; }
但若不止一个需要赋值的变量,则value
也需要键值对的形式
直接通过获取即可
// 获取Member的实例变量 Class<?> cl = Member.class; // 查找该类上是否有相应的注解 Entity entity = cl.getAnnotation(Entity.class); // 获取注解中的成员变量值 String name = entity.value();
除了上面几种用于定义注解的注解外,java还为我们提供了另外五个注解,Java 5 引入了前三种定义在 java.lang 包中的注解:
对于注解我们可以理解为一个标签,本质上是一个特殊的接口,他的功能主要有如下几点:
java注解是怎么实现的?
Java 注解完全解析
第二十三章 注解
本文保留所有权利,版权归河北工业大学梦云智软件开发团队所有。未经团队及作者事先书面同意,您不得以任何方式将本文内容进行商业性使用或通过信息网络传播本文内容。