在现实生活中,贴标签这种现象比比皆是。去超市,去商场,每一个或者每类物品都会有它的标签,甚至在咱们本身身上也会有标签,好比,程序猿、逗逼、单身狗、80/90后、屌丝……呵呵,太多了。有时候,咱们也会戏谑朋友同事,给他们贴个标签逗逗乐。可是这篇的正题是注解,下面我会说说为何我理解的注解就是贴标签,虽然有时候也会称它为“扣帽子”。java
在java提供了四个元注解,元注解就是注解的注解。它们是:spring
1.@Target, 2.@Retention, 3.@Documented, 4.@Inherited
在咱们刚出生的时候,就已经被贴上标签了,咱们的户籍按照地域划分,会被贴上河南河北、山东山西、湖南湖北等等23个省和四个直辖市中的其中一个。另外在咱们的生命过程当中也会经历标签的变换,小孩、未成年人、成年人、丈夫、妻子、父亲、母亲、爷爷奶奶等等。国家还会给咱们贴上一个最普通的标签“公民”以及咱们的继承的身份,农民或者城里人。为何要说这些呢,由于JAVA中提供的四个元注解要表达的东西和提到的有共通之处。sql
@Target说明了注解修饰的范围,就好像咱们有地域划分,而Java中也会有包、接口、类、枚举、属性、方法、构造函数等。那么为了表示不一样的区别,注解是这么写的:app
一、包 @Target(ElementType.PACKAGE)
二、接口、类、枚举、注解 @Target(ElementType.TYPE)
三、注解 @Target(ElementType.ANNOTATION_TYPE)
四、构造函数 @Target(ElementType.CONSTRUCTOR)
五、局部变量 @Target(ElementType.LOCAL_VARIABLE)
六、方法 @Target(ElementType.METHOD)
七、方法的参数 @Target(ElementType.PARAMETER)
@Retention表示了注解的生命周期。咱们在生命过程当中会随着时间的变化而引发标签的变化,那么咱们的标签自己也就说明了它有必定的生命周期,当咱们未满18周岁的时候叫未成年人,在咱们满18周岁的时候叫作成年人,等头发白了,走不动就被叫作老年人,而有的标签会伴随一辈子,例如男人或者女人。在JAVA中,注解也有它的生命周期,从源代码到编译后的Class文件,再到被JDK加载后的运行时就是整个周期。@Retention指定了它所要注解的注解的生命周期是什么,它会存在多长时间。JAVA中咱们最多见的两个注解@SuppressWarnings和@Override,他们就只会存在于源代码中。下面是@Retention的取值:ide
一、在源代码中保留 @Retention( RetentionPolicy.SOURCE)
二、在Class文件中保留 @Retention( RetentionPolicy.CLASS)
三、在运行时保留 @Retention( RetentionPolicy.RUNTIME)
@SuppressWarnings注解的源代码以下:函数
package java.lang; import java.lang.annotation.*; import java.lang.annotation.ElementType; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); }
默认状况下javadoc是不包括注解信息的,可是当某一个注解被贴上@Documented标签的时候,那么当某个类或者方法的使用了被贴上@Documented这个标签的注解的时候,javadoc就会把注解信息也包含在生成的文档中。这个注解就不过分解读了,若是有兴趣的能够从网上自行查找相关资料。ui
@Inherited注解主要说明了一种继承性,意思是子类能够继承父类中的该注解(注意:只有当被贴上@Inherited标签的注解被用在类上的时候子类才能得到这个注解)。就像以前提到的,若是父母是农村户口,那么他们的孩子也默认就是农村户口了。Spring中的@Qualifier注解,代码以下:this
package org.springframework.beans.factory.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Qualifier { String value() default ""; }
@Qualifier注解能够被用在字段、方法、方法参数、类、接口、注解、枚举上,可是只有@Qualifier被用在类上的时候才能被它的子类继承,子类才能够获取到这个注解。spa
除了一些咱们生来就被贴上的标签意外,咱们在平常生活中不论是主动的仍是被动都会去主动的给别人贴一些标签以及被别人贴一些标签。当咱们在公司,按照职能划分,会被贴上不一样的岗位标签,便于安排工做;迟到,早退,全勤这些标签用于考勤;优秀员工,技术达人,管理精英等标签用来树立标杆,有助于提升积极性和向心力。那么这些标签被创造出来有没有用处呢,对于公司来讲天然是有用处的。可是呢,逗逼这个标签对公司来讲有没有用处呢,我想,除非公司愿意由于员工逗逼颁发逗逼奖这才有点用处,不然的话谁关心呢!贴个标签大多数时候并不会影响正常的生活,除了我的或者组织关注了你身上的标签的时候才会有影响,就像如今不少人一看到河南人三个字就开骂了同样……。其实这也是为了说明,注解并不会影响程序的正常运行,有或者没有并不影响什么,只有关注了这些注解的程序得到而且解析了注解进行处理之后才会更改程序自己的行为。code
咱们知道JAVA的JDK中不少地方都用了注解,到咱们使用Spring的时候,注解就被使用的更普遍了,Spring用注解来对bean进行分类,注册,注入以及管理,这些事情是Spring在扫描Bean的时候经过反射来获取Bean的注解信息,配合完成Bean的自动装配,进而进行管理,给咱们提供了丰富多彩的功能。下面写一个利用反射来处理自定义注解的例子,这个例子就是简单生成一个建表语句,代码以下:
一、建立@Table注解
package person.lb.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 表名 * @author nobounds * */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table { String value() default ""; }
二、建立@Column注解:
package person.lb.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 字段 * @author nobounds * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String name() default ""; String dataType() default "varchar(20)"; String comment() default ""; }
三、建立实体类Users:
package person.lb.annotation; @Table("users") public class Users { @Column(name="ID", dataType="int") private int id; @Column(comment="用户名") private String userName; @Column(name="pwd", comment="密码") private String password; @Column(dataType="varchar(25)", comment="邮箱") private String email; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
四、建立注解处理器AnnotationHandler:
package person.lb.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Field; public class AnnotationHandler { public static void main(String[] args) { StringBuilder sql = new StringBuilder("CREATE TABLE "); try { Class clazz = Class.forName("person.lb.annotation.Users"); //获取Users类上的Table注解 Table tableAnnotation = (Table) clazz.getAnnotation(Table.class); //获取表名 String tableName = tableAnnotation.value().toUpperCase(); if("".equals(tableName)) { tableName = clazz.getName().toUpperCase(); } sql.append(tableName); sql.append(" ( \n"); //获取类中的全部字段 Field[] fields = clazz.getDeclaredFields(); for(Field field : fields) { //获取字段上的全部注解 Annotation[] fieldAnnotations = field.getAnnotations(); if(fieldAnnotations.length > 0) { //遍历注解 for(Annotation fieldAnnotation : fieldAnnotations) { //若是是@Field注解,那么进行处理 if(fieldAnnotation instanceof Column) { //获取字段名 String columnName = ((Column) fieldAnnotation).name().toUpperCase(); if("".equals(columnName)) { columnName = field.getName().toUpperCase(); } //获取数据类型 String dataType = ((Column) fieldAnnotation).dataType().toUpperCase(); //获取注释 String comment = ((Column) fieldAnnotation).comment(); if("".equals(comment)) { sql.append(columnName + "\t" + dataType + ",\n"); } else { sql.append(columnName + "\t" + dataType + " COMMENT '" + comment + "',\n"); } } } } } sql.append(" ) "); System.out.println("生成的sql语句为:\n" + sql.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
执行结果以下:
生成的sql语句为: CREATE TABLE USERS ( ID INT, USERNAME VARCHAR(20) COMMENT '用户名', PWD VARCHAR(20) COMMENT '密码', EMAIL VARCHAR(25) COMMENT '邮箱', )
上面是一个简单的生成sql的例子,例子中忽略了某些非空判断,逻辑并不严谨,仅做为参考使用。若是你们以为有问题请留言!